diff --git a/src/sys/create.c b/src/sys/create.c index dfda7923..e9db650b 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -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( diff --git a/src/sys/device.c b/src/sys/device.c index 9cda6a30..d8461554 100644 --- a/src/sys/device.c +++ b/src/sys/device.c @@ -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(); diff --git a/src/sys/driver.h b/src/sys/driver.h index 02b7504a..da7d03bc 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -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); diff --git a/src/sys/fileinfo.c b/src/sys/fileinfo.c index 17f9a324..ee46f134 100644 --- a/src/sys/fileinfo.c +++ b/src/sys/fileinfo.c @@ -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(); diff --git a/src/sys/iop.c b/src/sys/iop.c index cc311ea5..044dee99 100644 --- a/src/sys/iop.c +++ b/src/sys/iop.c @@ -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;