From 51350d5a4256a07b141f5b911410f2db693aba6e Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Mon, 3 Feb 2020 14:59:23 -0800 Subject: [PATCH 1/4] inc,sys,tst: FSP_FSCTL_VOLUME_PARAMS::RejectIrpPriorToTransact --- build/VStudio/testing/memfs.vcxproj | 8 ++++---- inc/winfsp/fsctl.h | 3 ++- src/sys/create.c | 3 +++ src/sys/driver.h | 17 +++++++++++++++++ src/sys/volinfo.c | 6 ++++++ src/sys/volume.c | 4 ++++ tst/memfs/memfs.cpp | 19 ++++++++++++++++++- 7 files changed, 54 insertions(+), 6 deletions(-) diff --git a/build/VStudio/testing/memfs.vcxproj b/build/VStudio/testing/memfs.vcxproj index 65db905d..80b0a4f9 100644 --- a/build/VStudio/testing/memfs.vcxproj +++ b/build/VStudio/testing/memfs.vcxproj @@ -101,7 +101,7 @@ Level3 Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + MEMFS_STANDALONE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true ..\..\..\src;..\..\..\inc MultiThreaded @@ -117,7 +117,7 @@ Level3 Disabled - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + MEMFS_STANDALONE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true ..\..\..\src;..\..\..\inc MultiThreaded @@ -135,7 +135,7 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MEMFS_STANDALONE;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true ..\..\..\src;..\..\..\inc MultiThreaded @@ -155,7 +155,7 @@ MaxSpeed true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MEMFS_STANDALONE;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true ..\..\..\src;..\..\..\inc MultiThreaded diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index cdd4914e..f0d252c5 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -176,7 +176,8 @@ enum UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\ UINT32 WslFeatures:1; /* support features required for WSLinux */\ UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\ - UINT32 KmReservedFlags:4;\ + UINT32 RejectIrpPriorToTransact:1; /* reject IRP's prior to first FSP_FSCTL_TRANSACT */\ + UINT32 KmReservedFlags:3;\ WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\ WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)]; #define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\ diff --git a/src/sys/create.c b/src/sys/create.c index bbcd3344..f5d73dfd 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -284,6 +284,9 @@ static NTSTATUS FspFsvolCreateNoLock( return STATUS_SUCCESS; } + if (!FspFsvolDeviceReadyToAcceptIrp(FsvolDeviceObject)) + return STATUS_CANCELLED; + PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState; ULONG CreateDisposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff; ULONG CreateOptions = IrpSp->Parameters.Create.Options; diff --git a/src/sys/driver.h b/src/sys/driver.h index 85164a7f..fbbabf32 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -1082,6 +1082,7 @@ typedef struct FSP_FSEXT_PROVIDER *Provider; UNICODE_STRING VolumePrefix; UNICODE_PREFIX_TABLE_ENTRY VolumePrefixEntry; + LONG ReadyToAcceptIrp; FSP_IOQ *Ioq; FSP_META_CACHE *SecurityCache; FSP_META_CACHE *DirInfoCache; @@ -1182,6 +1183,22 @@ BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VO VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject); static inline +BOOLEAN FspFsvolDeviceReadyToAcceptIrp(PDEVICE_OBJECT DeviceObject) +{ + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); + if (!FsvolDeviceExtension->VolumeParams.RejectIrpPriorToTransact) + return TRUE; + return 0 != InterlockedCompareExchange(&FsvolDeviceExtension->ReadyToAcceptIrp, 0, 0); +} +static inline +VOID FspFsvolDeviceSetReadyToAcceptIrp(PDEVICE_OBJECT DeviceObject) +{ + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); + if (!FsvolDeviceExtension->VolumeParams.RejectIrpPriorToTransact) + return; + InterlockedExchange(&FsvolDeviceExtension->ReadyToAcceptIrp, 1); +} +static inline BOOLEAN FspFsvolDeviceVolumePrefixInString(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING String) { return RtlPrefixUnicodeString(&FspFsvolDeviceExtension(DeviceObject)->VolumePrefix, String, diff --git a/src/sys/volinfo.c b/src/sys/volinfo.c index c82b8e63..3dccaf77 100644 --- a/src/sys/volinfo.c +++ b/src/sys/volinfo.c @@ -286,6 +286,9 @@ static NTSTATUS FspFsvolQueryVolumeInformation( { PAGED_CODE(); + if (!FspFsvolDeviceReadyToAcceptIrp(FsvolDeviceObject)) + return STATUS_CANCELLED; + NTSTATUS Result; PUINT8 Buffer = Irp->AssociatedIrp.SystemBuffer; PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryVolume.Length; @@ -414,6 +417,9 @@ static NTSTATUS FspFsvolSetVolumeInformation( { PAGED_CODE(); + if (!FspFsvolDeviceReadyToAcceptIrp(FsvolDeviceObject)) + return STATUS_CANCELLED; + NTSTATUS Result; FS_INFORMATION_CLASS FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass; PVOID Buffer = Irp->AssociatedIrp.SystemBuffer; diff --git a/src/sys/volume.c b/src/sys/volume.c index a597a16c..8839612f 100644 --- a/src/sys/volume.c +++ b/src/sys/volume.c @@ -277,6 +277,8 @@ static NTSTATUS FspVolumeCreateNoLock( RtlInitEmptyUnicodeString(&FsvolDeviceExtension->VolumeName, FsvolDeviceExtension->VolumeNameBuf, sizeof FsvolDeviceExtension->VolumeNameBuf); RtlCopyUnicodeString(&FsvolDeviceExtension->VolumeName, &VolumeName); + if (!FsvolDeviceExtension->VolumeParams.RejectIrpPriorToTransact) + FsvolDeviceExtension->ReadyToAcceptIrp = 1; Result = FspDeviceInitialize(FsvolDeviceObject); if (NT_SUCCESS(Result)) { @@ -767,6 +769,8 @@ NTSTATUS FspVolumeTransact( if (!FspDeviceReference(FsvolDeviceObject)) return STATUS_CANCELLED; + FspFsvolDeviceSetReadyToAcceptIrp(FsvolDeviceObject); + NTSTATUS Result; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); PUINT8 BufferEnd; diff --git a/tst/memfs/memfs.cpp b/tst/memfs/memfs.cpp index efd86a35..be169cb3 100644 --- a/tst/memfs/memfs.cpp +++ b/tst/memfs/memfs.cpp @@ -34,6 +34,12 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH, "MEMFS_MAX_PATH must be greater than MAX_PATH."); +/* + * Define the MEMFS_STANDALONE macro when building MEMFS as a standalone file system. + * This macro should be defined in the Visual Studio project settings, Makefile, etc. + */ +//#define MEMFS_STANDALONE + /* * Define the MEMFS_NAME_NORMALIZATION macro to include name normalization support. */ @@ -74,7 +80,15 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH, */ #define MEMFS_WSL - /* +/* + * Define the MEMFS_REJECT_EARLY_IRP macro to reject IRP's sent + * to the file system prior to FSP_FSCTL_TRANSACT. + */ +#if defined(MEMFS_STANDALONE) +#define MEMFS_REJECT_EARLY_IRP +#endif + +/* * Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes * a check for the Write buffer to ensure that it is read-only. * @@ -2387,6 +2401,9 @@ NTSTATUS MemfsCreateFunnel( VolumeParams.WslFeatures = 1; #endif VolumeParams.AllowOpenInKernelMode = 1; +#if defined(MEMFS_REJECT_EARLY_IRP) + VolumeParams.RejectIrpPriorToTransact = 1; +#endif if (0 != VolumePrefix) wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix); wcscpy_s(VolumeParams.FileSystemName, sizeof VolumeParams.FileSystemName / sizeof(WCHAR), From bf6d56ceac0bc7cbd767bbaa994f69dc13e8ab69 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Mon, 3 Feb 2020 16:38:55 -0800 Subject: [PATCH 2/4] inc,sys,tst: FSP_FSCTL_VOLUME_PARAMS::RejectIrpPriorToTransact0 --- inc/winfsp/fsctl.h | 2 +- src/dll/fs.c | 5 +++++ src/sys/driver.h | 4 ++-- src/sys/volume.c | 5 +++-- tst/memfs/memfs.cpp | 2 +- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index f0d252c5..353bf5fb 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -176,7 +176,7 @@ enum UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\ UINT32 WslFeatures:1; /* support features required for WSLinux */\ UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\ - UINT32 RejectIrpPriorToTransact:1; /* reject IRP's prior to first FSP_FSCTL_TRANSACT */\ + UINT32 RejectIrpPriorToTransact0:1; /* reject IRP's prior to FspFsctlTransact with 0 buffers */\ UINT32 KmReservedFlags:3;\ WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\ WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)]; diff --git a/src/dll/fs.c b/src/dll/fs.c index 5b68e546..aa6e956a 100644 --- a/src/dll/fs.c +++ b/src/dll/fs.c @@ -273,6 +273,11 @@ static DWORD WINAPI FspFileSystemDispatcherThread(PVOID FileSystem0) OperationContext.Response = Response; TlsSetValue(FspFileSystemTlsKey, &OperationContext); + Result = FspFsctlTransact(FileSystem->VolumeHandle, 0, 0, 0, 0, FALSE); + /* send a TRANSACT0 to inform the FSD that the dispatcher is ready */ + if (!NT_SUCCESS(Result)) + goto exit; + memset(Response, 0, sizeof *Response); for (;;) { diff --git a/src/sys/driver.h b/src/sys/driver.h index fbbabf32..155b2cc5 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -1186,7 +1186,7 @@ static inline BOOLEAN FspFsvolDeviceReadyToAcceptIrp(PDEVICE_OBJECT DeviceObject) { FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); - if (!FsvolDeviceExtension->VolumeParams.RejectIrpPriorToTransact) + if (!FsvolDeviceExtension->VolumeParams.RejectIrpPriorToTransact0) return TRUE; return 0 != InterlockedCompareExchange(&FsvolDeviceExtension->ReadyToAcceptIrp, 0, 0); } @@ -1194,7 +1194,7 @@ static inline VOID FspFsvolDeviceSetReadyToAcceptIrp(PDEVICE_OBJECT DeviceObject) { FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); - if (!FsvolDeviceExtension->VolumeParams.RejectIrpPriorToTransact) + if (!FsvolDeviceExtension->VolumeParams.RejectIrpPriorToTransact0) return; InterlockedExchange(&FsvolDeviceExtension->ReadyToAcceptIrp, 1); } diff --git a/src/sys/volume.c b/src/sys/volume.c index 8839612f..ff007745 100644 --- a/src/sys/volume.c +++ b/src/sys/volume.c @@ -277,7 +277,7 @@ static NTSTATUS FspVolumeCreateNoLock( RtlInitEmptyUnicodeString(&FsvolDeviceExtension->VolumeName, FsvolDeviceExtension->VolumeNameBuf, sizeof FsvolDeviceExtension->VolumeNameBuf); RtlCopyUnicodeString(&FsvolDeviceExtension->VolumeName, &VolumeName); - if (!FsvolDeviceExtension->VolumeParams.RejectIrpPriorToTransact) + if (!FsvolDeviceExtension->VolumeParams.RejectIrpPriorToTransact0) FsvolDeviceExtension->ReadyToAcceptIrp = 1; Result = FspDeviceInitialize(FsvolDeviceObject); if (NT_SUCCESS(Result)) @@ -769,7 +769,8 @@ NTSTATUS FspVolumeTransact( if (!FspDeviceReference(FsvolDeviceObject)) return STATUS_CANCELLED; - FspFsvolDeviceSetReadyToAcceptIrp(FsvolDeviceObject); + if (0 == InputBufferLength && 0 == OutputBufferLength) + FspFsvolDeviceSetReadyToAcceptIrp(FsvolDeviceObject); NTSTATUS Result; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); diff --git a/tst/memfs/memfs.cpp b/tst/memfs/memfs.cpp index be169cb3..8e1e97c1 100644 --- a/tst/memfs/memfs.cpp +++ b/tst/memfs/memfs.cpp @@ -2402,7 +2402,7 @@ NTSTATUS MemfsCreateFunnel( #endif VolumeParams.AllowOpenInKernelMode = 1; #if defined(MEMFS_REJECT_EARLY_IRP) - VolumeParams.RejectIrpPriorToTransact = 1; + VolumeParams.RejectIrpPriorToTransact0 = 1; #endif if (0 != VolumePrefix) wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix); From 0901fb64778ec6d1caa305caaf9d29d1030d64b1 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Mon, 3 Feb 2020 16:43:15 -0800 Subject: [PATCH 3/4] inc,sys,tst: FSP_FSCTL_VOLUME_PARAMS::RejectIrpPriorToTransact0 --- src/dll/fs.c | 2 +- tst/memfs/memfs.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dll/fs.c b/src/dll/fs.c index aa6e956a..e2c36804 100644 --- a/src/dll/fs.c +++ b/src/dll/fs.c @@ -274,7 +274,7 @@ static DWORD WINAPI FspFileSystemDispatcherThread(PVOID FileSystem0) TlsSetValue(FspFileSystemTlsKey, &OperationContext); Result = FspFsctlTransact(FileSystem->VolumeHandle, 0, 0, 0, 0, FALSE); - /* send a TRANSACT0 to inform the FSD that the dispatcher is ready */ + /* send a Transact0 to inform the FSD that the dispatcher is ready */ if (!NT_SUCCESS(Result)) goto exit; diff --git a/tst/memfs/memfs.cpp b/tst/memfs/memfs.cpp index 8e1e97c1..1cc3ba7e 100644 --- a/tst/memfs/memfs.cpp +++ b/tst/memfs/memfs.cpp @@ -82,7 +82,7 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH, /* * Define the MEMFS_REJECT_EARLY_IRP macro to reject IRP's sent - * to the file system prior to FSP_FSCTL_TRANSACT. + * to the file system prior to the dispatcher being started. */ #if defined(MEMFS_STANDALONE) #define MEMFS_REJECT_EARLY_IRP From 8497855d80e5ed9a46844971c12ea786ff5ae08a Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Fri, 7 Feb 2020 13:22:09 -0800 Subject: [PATCH 4/4] sys: FSP_DEVICE_REJECT_EARLY_IRP macro --- src/sys/create.c | 2 ++ src/sys/driver.h | 5 +++++ src/sys/volinfo.c | 4 ++++ src/sys/volume.c | 4 ++++ 4 files changed, 15 insertions(+) diff --git a/src/sys/create.c b/src/sys/create.c index f5d73dfd..4b34372d 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -284,8 +284,10 @@ static NTSTATUS FspFsvolCreateNoLock( return STATUS_SUCCESS; } +#if defined(FSP_DEVICE_REJECT_EARLY_IRP) if (!FspFsvolDeviceReadyToAcceptIrp(FsvolDeviceObject)) return STATUS_CANCELLED; +#endif PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState; ULONG CreateDisposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff; diff --git a/src/sys/driver.h b/src/sys/driver.h index 155b2cc5..b6da6824 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -1028,6 +1028,7 @@ NTSTATUS FspStatisticsCopy(FSP_STATISTICS *Statistics, PVOID Buffer, PULONG PLen #define FspStatisticsAdd(S,F,V) ((S)->F += (V)) /* device management */ +#define FSP_DEVICE_REJECT_EARLY_IRP enum { FspFsvolDeviceSecurityCacheCapacity = 100, @@ -1082,7 +1083,9 @@ typedef struct FSP_FSEXT_PROVIDER *Provider; UNICODE_STRING VolumePrefix; UNICODE_PREFIX_TABLE_ENTRY VolumePrefixEntry; +#if defined(FSP_DEVICE_REJECT_EARLY_IRP) LONG ReadyToAcceptIrp; +#endif FSP_IOQ *Ioq; FSP_META_CACHE *SecurityCache; FSP_META_CACHE *DirInfoCache; @@ -1182,6 +1185,7 @@ VOID FspFsvolDeviceGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_I BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject); +#if defined(FSP_DEVICE_REJECT_EARLY_IRP) static inline BOOLEAN FspFsvolDeviceReadyToAcceptIrp(PDEVICE_OBJECT DeviceObject) { @@ -1198,6 +1202,7 @@ VOID FspFsvolDeviceSetReadyToAcceptIrp(PDEVICE_OBJECT DeviceObject) return; InterlockedExchange(&FsvolDeviceExtension->ReadyToAcceptIrp, 1); } +#endif static inline BOOLEAN FspFsvolDeviceVolumePrefixInString(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING String) { diff --git a/src/sys/volinfo.c b/src/sys/volinfo.c index 3dccaf77..4ffda23e 100644 --- a/src/sys/volinfo.c +++ b/src/sys/volinfo.c @@ -286,8 +286,10 @@ static NTSTATUS FspFsvolQueryVolumeInformation( { PAGED_CODE(); +#if defined(FSP_DEVICE_REJECT_EARLY_IRP) if (!FspFsvolDeviceReadyToAcceptIrp(FsvolDeviceObject)) return STATUS_CANCELLED; +#endif NTSTATUS Result; PUINT8 Buffer = Irp->AssociatedIrp.SystemBuffer; @@ -417,8 +419,10 @@ static NTSTATUS FspFsvolSetVolumeInformation( { PAGED_CODE(); +#if defined(FSP_DEVICE_REJECT_EARLY_IRP) if (!FspFsvolDeviceReadyToAcceptIrp(FsvolDeviceObject)) return STATUS_CANCELLED; +#endif NTSTATUS Result; FS_INFORMATION_CLASS FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass; diff --git a/src/sys/volume.c b/src/sys/volume.c index ff007745..992552df 100644 --- a/src/sys/volume.c +++ b/src/sys/volume.c @@ -277,8 +277,10 @@ static NTSTATUS FspVolumeCreateNoLock( RtlInitEmptyUnicodeString(&FsvolDeviceExtension->VolumeName, FsvolDeviceExtension->VolumeNameBuf, sizeof FsvolDeviceExtension->VolumeNameBuf); RtlCopyUnicodeString(&FsvolDeviceExtension->VolumeName, &VolumeName); +#if defined(FSP_DEVICE_REJECT_EARLY_IRP) if (!FsvolDeviceExtension->VolumeParams.RejectIrpPriorToTransact0) FsvolDeviceExtension->ReadyToAcceptIrp = 1; +#endif Result = FspDeviceInitialize(FsvolDeviceObject); if (NT_SUCCESS(Result)) { @@ -769,8 +771,10 @@ NTSTATUS FspVolumeTransact( if (!FspDeviceReference(FsvolDeviceObject)) return STATUS_CANCELLED; +#if defined(FSP_DEVICE_REJECT_EARLY_IRP) if (0 == InputBufferLength && 0 == OutputBufferLength) FspFsvolDeviceSetReadyToAcceptIrp(FsvolDeviceObject); +#endif NTSTATUS Result; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);