sys: FileRenameResource implementation

This commit is contained in:
Bill Zissimopoulos 2016-02-07 11:01:15 -08:00
parent 3ef9042071
commit 9c200f2a62
5 changed files with 135 additions and 30 deletions

View File

@ -12,6 +12,8 @@ static NTSTATUS FspFsvrtCreate(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsvolCreate(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsvolCreateNoLock(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response,
@ -27,6 +29,7 @@ FSP_DRIVER_DISPATCH FspCreate;
#pragma alloc_text(PAGE, FspFsctlCreate)
#pragma alloc_text(PAGE, FspFsvrtCreate)
#pragma alloc_text(PAGE, FspFsvolCreate)
#pragma alloc_text(PAGE, FspFsvolCreateNoLock)
#pragma alloc_text(PAGE, FspFsvolCreatePrepare)
#pragma alloc_text(PAGE, FspFsvolCreateComplete)
#pragma alloc_text(PAGE, FspFsvolCreateTryOpen)
@ -43,14 +46,16 @@ FSP_DRIVER_DISPATCH FspCreate;
enum
{
/* Create */
RequestFileDesc = 0,
RequestAccessToken = 1,
RequestProcess = 2,
RequestDeviceObject = 0,
RequestFileDesc = 1,
RequestAccessToken = 2,
RequestProcess = 3,
/* TryOpen/Overwrite */
//RequestFileDesc = 0,
RequestFileObject = 1,
RequestState = 2,
//RequestDeviceObject = 0,
//RequestFileDesc = 1,
RequestFileObject = 2,
RequestState = 3,
/* RequestState */
RequestPending = 0,
@ -92,6 +97,27 @@ static NTSTATUS FspFsvolCreate(
{
PAGED_CODE();
NTSTATUS Result = STATUS_SUCCESS;
FspFsvolDeviceFileRenameAcquireShared(FsvolDeviceObject);
try
{
Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp);
}
finally
{
if (FSP_STATUS_IOQ_POST != Result)
FspFsvolDeviceFileRenameRelease(FsvolDeviceObject);
}
return Result;
}
static NTSTATUS FspFsvolCreateNoLock(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
NTSTATUS Result;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PFILE_OBJECT FileObject = IrpSp->FileObject;
@ -180,6 +206,11 @@ static NTSTATUS FspFsvolCreate(
{
RelatedFileNode = RelatedFileObject->FsContext;
/*
* Accesses of RelatedFileNode->FileName are protected
* by FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource.
*/
/* is this a valid RelatedFileObject? */
if (!FspFileNodeIsValid(RelatedFileNode))
return STATUS_OBJECT_PATH_NOT_FOUND;
@ -202,12 +233,6 @@ static NTSTATUS FspFsvolCreate(
sizeof(WCHAR) == RelatedFileNode->FileName.Length && 0 == FileName.Length)
return STATUS_CANNOT_DELETE;
/*
* There is no need to lock our accesses of RelatedFileObject->FileNode->FileName,
* because RelatedFileObject->FileNode->Filename is read-only (after creation) and
* because RelatedFileObject->FileNode is guaranteed to exist while RelatedFileObject
* exists.
*/
BOOLEAN AppendBackslash =
sizeof(WCHAR) * 2/* not empty or root */ <= RelatedFileNode->FileName.Length &&
sizeof(WCHAR) <= FileName.Length && L':' != FileName.Buffer[0];
@ -320,6 +345,8 @@ static NTSTATUS FspFsvolCreate(
* delete the Request and any associated resources.
*/
FileDesc->FileNode = FileNode;
FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request);
FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject;
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
/* populate the Create request */
@ -589,25 +616,20 @@ NTSTATUS FspFsvolCreateComplete(
if (FileNode->IsDirectory)
SetFlag(FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
/* delete the old request */
FspIrpRequest(Irp) = 0;
/* disassociate the FileDesc momentarily from the Request */
FspIopRequestContext(Request, RequestDeviceObject) = 0;
FspIopRequestContext(Request, RequestFileDesc) = 0;
/* disassociate the FileDesc from the old Request as we want to keep it around! */
FspIopDeleteRequest(Request);
/* create the Overwrite request; MustSucceed because we must either overwrite or close */
FspIopCreateRequestFunnel(Irp,
FsvolDeviceExtension->VolumeParams.FileNameRequired ? &FileNode->FileName : 0, 0,
FspFsvolCreateOverwriteRequestFini, TRUE,
&Request);
/* associate the FileDesc and FileObject with the Overwrite request */
/* reset the request */
Request->Kind = FspFsctlTransactOverwriteKind;
RtlZeroMemory(&Request->Req.Create, sizeof Request->Req.Create);
FspIopResetRequest(Request, FspFsvolCreateOverwriteRequestFini);
FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject;
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
FspIopRequestContext(Request, RequestFileObject) = FileObject;
FspIopRequestContext(Request, RequestState) = (PVOID)RequestPending;
/* populate the Overwrite request */
Request->Kind = FspFsctlTransactOverwriteKind;
Request->Req.Overwrite.UserContext = FileNode->UserContext;
Request->Req.Overwrite.UserContext2 = FileDesc->UserContext2;
Request->Req.Overwrite.FileAttributes = FileAttributes;
@ -681,13 +703,17 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re
if (FspFsctlTransactCreateKind == Request->Kind)
{
PDEVICE_OBJECT FsvolDeviceObject = FspIopRequestContext(Request, RequestDeviceObject);
/* disassociate the FileDesc momentarily from the Request */
Request = FspIrpRequest(Irp);
FspIopRequestContext(Request, RequestDeviceObject) = 0;
FspIopRequestContext(Request, RequestFileDesc) = 0;
/* reset the Request and reassociate the FileDesc and FileObject with it */
Request->Kind = FspFsctlTransactReservedKind;
FspIopResetRequest(Request, FspFsvolCreateTryOpenRequestFini);
FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject;
FspIopRequestContext(Request, RequestFileDesc) = FileDesc;
FspIopRequestContext(Request, RequestFileObject) = FileObject;
FspIopRequestContext(Request, RequestState) = (PVOID)(UINT_PTR)FlushImage;
@ -761,10 +787,11 @@ static VOID FspFsvolCreatePostClose(FSP_FILE_DESC *FileDesc)
*/
}
static VOID FspFsvolCreateRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[3])
static VOID FspFsvolCreateRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
{
PAGED_CODE();
PDEVICE_OBJECT FsvolDeviceObject = Context[RequestDeviceObject];
FSP_FILE_DESC *FileDesc = Context[RequestFileDesc];
HANDLE AccessToken = Context[RequestAccessToken];
PEPROCESS Process = Context[RequestProcess];
@ -798,12 +825,16 @@ static VOID FspFsvolCreateRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Con
ObDereferenceObject(Process);
}
if (0 != FsvolDeviceObject)
FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, Request);
}
static VOID FspFsvolCreateTryOpenRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[3])
static VOID FspFsvolCreateTryOpenRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
{
PAGED_CODE();
PDEVICE_OBJECT FsvolDeviceObject = Context[RequestDeviceObject];
FSP_FILE_DESC *FileDesc = Context[RequestFileDesc];
PFILE_OBJECT FileObject = Context[RequestFileObject];
@ -816,12 +847,16 @@ static VOID FspFsvolCreateTryOpenRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PV
FspFileNodeDereference(FileDesc->FileNode);
FspFileDescDelete(FileDesc);
}
if (0 != FsvolDeviceObject)
FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, Request);
}
static VOID FspFsvolCreateOverwriteRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[3])
static VOID FspFsvolCreateOverwriteRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
{
PAGED_CODE();
PDEVICE_OBJECT FsvolDeviceObject = Context[RequestDeviceObject];
FSP_FILE_DESC *FileDesc = Context[RequestFileDesc];
PFILE_OBJECT FileObject = Context[RequestFileObject];
ULONG State = (ULONG)(UINT_PTR)Context[RequestState];
@ -839,6 +874,9 @@ static VOID FspFsvolCreateOverwriteRequestFini(FSP_FSCTL_TRANSACT_REQ *Request,
FspFileNodeDereference(FileDesc->FileNode);
FspFileDescDelete(FileDesc);
}
if (0 != FsvolDeviceObject)
FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, Request);
}
NTSTATUS FspCreate(

View File

@ -25,6 +25,11 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject);
static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject);
static IO_TIMER_ROUTINE FspFsvolDeviceTimerRoutine;
static WORKER_THREAD_ROUTINE FspFsvolDeviceExpirationRoutine;
VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
PVOID FspFsvolDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier);
@ -60,6 +65,11 @@ VOID FspDeviceDeleteAll(VOID);
#pragma alloc_text(PAGE, FspDeviceDelete)
#pragma alloc_text(PAGE, FspFsvolDeviceInit)
#pragma alloc_text(PAGE, FspFsvolDeviceFini)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameAcquireShared)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameAcquireExclusive)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner)
#pragma alloc_text(PAGE, FspFsvolDeviceLockContextTable)
#pragma alloc_text(PAGE, FspFsvolDeviceUnlockContextTable)
#pragma alloc_text(PAGE, FspFsvolDeviceLookupContext)
@ -437,6 +447,58 @@ static VOID FspFsvolDeviceExpirationRoutine(PVOID Context)
FspDeviceDereference(DeviceObject);
}
VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExAcquireResourceSharedLite(&FsvolDeviceExtension->FileRenameResource, TRUE);
}
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->FileRenameResource, TRUE);
}
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
Owner = (PVOID)((UINT_PTR)Owner | 3);
ExSetResourceOwnerPointer(&FsvolDeviceExtension->FileRenameResource, Owner);
}
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExReleaseResourceLite(&FsvolDeviceExtension->FileRenameResource);
}
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
Owner = (PVOID)((UINT_PTR)Owner | 3);
if (ExIsResourceAcquiredLite(&FsvolDeviceExtension->FileRenameResource))
ExReleaseResourceLite(&FsvolDeviceExtension->FileRenameResource);
else
ExReleaseResourceForThreadLite(&FsvolDeviceExtension->FileRenameResource, (ERESOURCE_THREAD)Owner);
}
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();

View File

@ -419,7 +419,7 @@ PIRP FspIoqNextCompleteIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp);
#define FspIopPostWorkRequestBestEffort(D, R)\
FspIopPostWorkRequestFunnel(D, R, TRUE)
#define FspIopCompleteIrp(I, R) FspIopCompleteIrpEx(I, R, TRUE)
typedef VOID FSP_IOP_REQUEST_FINI(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[3]);
typedef VOID FSP_IOP_REQUEST_FINI(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]);
NTSTATUS FspIopCreateRequestFunnel(
PIRP Irp, PUNICODE_STRING FileName, ULONG ExtraSize, FSP_IOP_REQUEST_FINI *RequestFini,
BOOLEAN MustSucceed,
@ -522,6 +522,11 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
PVOID FspFsvolDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier);

View File

@ -851,7 +851,7 @@ NTSTATUS FspFsvolSetInformationComplete(
IrpSp->FileObject);
}
static VOID FspFsvolInformationRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[3])
static VOID FspFsvolInformationRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
{
PAGED_CODE();

View File

@ -84,7 +84,7 @@ static PVOID FspAllocateIrpMustSucceed(CCHAR StackSize)
typedef struct
{
FSP_IOP_REQUEST_FINI *RequestFini;
PVOID Context[3];
PVOID Context[4];
FSP_FSCTL_TRANSACT_RSP *Response;
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 RequestBuf[];
} FSP_FSCTL_TRANSACT_REQ_HEADER;