From 4ae03629f71e5a5fb9d665d84c95c138da22a3ed Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 18 Jun 2019 20:28:59 -0700 Subject: [PATCH] sys: FspFsextProvider: load provider driver --- src/sys/device.c | 11 ++++++--- src/sys/driver.h | 8 ++++++- src/sys/fsctl.c | 2 +- src/sys/fsext.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/sys/device.c b/src/sys/device.c index af4bcf29..321dcd6c 100644 --- a/src/sys/device.c +++ b/src/sys/device.c @@ -329,7 +329,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject) if (0 != FsvolDeviceExtension->VolumeParams.FsextControlCode) { FSP_FSEXT_PROVIDER *Provider = FspFsextProvider( - FsvolDeviceExtension->VolumeParams.FsextControlCode); + FsvolDeviceExtension->VolumeParams.FsextControlCode, &Result); if (0 != Provider) { Result = Provider->DeviceInit(DeviceObject, &FsvolDeviceExtension->VolumeParams); @@ -337,6 +337,11 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject) return Result; FsvolDeviceExtension->InitDoneFsext = 1; } + else + { + ASSERT(!NT_SUCCESS(Result)); + return Result; + } } /* is there a virtual disk? */ @@ -519,7 +524,7 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject) if (FsvolDeviceExtension->InitDoneFsext) { FSP_FSEXT_PROVIDER *Provider = FspFsextProvider( - FsvolDeviceExtension->VolumeParams.FsextControlCode); + FsvolDeviceExtension->VolumeParams.FsextControlCode, 0); if (0 != Provider) Provider->DeviceFini(DeviceObject); } @@ -573,7 +578,7 @@ static VOID FspFsvolDeviceExpirationRoutine(PVOID Context) if (0 != FsvolDeviceExtension->VolumeParams.FsextControlCode) { FSP_FSEXT_PROVIDER *Provider = FspFsextProvider( - FsvolDeviceExtension->VolumeParams.FsextControlCode); + FsvolDeviceExtension->VolumeParams.FsextControlCode, 0); if (0 != Provider) Provider->DeviceExpirationRoutine(DeviceObject, InterruptTime); } diff --git a/src/sys/driver.h b/src/sys/driver.h index b242d417..ecf63697 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -37,6 +37,12 @@ #define DRIVER_NAME FSP_FSCTL_DRIVER_NAME +#if _WIN64 +#define FSP_REGKEY "\\Registry\\Machine\\Software\\WOW6432Node\\WinFsp" +#else +#define FSP_REGKEY "\\Registry\\Machine\\Software\\WinFsp" +#endif + /* IoCreateDeviceSecure default SDDL's */ #define FSP_FSCTL_DEVICE_SDDL "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;WD)" /* System:GENERIC_ALL, Administrators:GENERIC_ALL, World:GENERIC_READ */ @@ -1182,7 +1188,7 @@ VOID FspDeviceGlobalUnlock(VOID) // STATUS_VOLUME_DISMOUNTED : STATUS_DEVICE_NOT_CONNECTED) /* fsext */ -FSP_FSEXT_PROVIDER *FspFsextProvider(UINT32 ControlCode); +FSP_FSEXT_PROVIDER *FspFsextProvider(UINT32 ControlCode, PNTSTATUS PLoadResult); /* process buffers conditional usage */ static inline diff --git a/src/sys/fsctl.c b/src/sys/fsctl.c index e000dfa4..2d90ebb8 100644 --- a/src/sys/fsctl.c +++ b/src/sys/fsctl.c @@ -113,7 +113,7 @@ static NTSTATUS FspFsctlFileSystemControl( FsvolDeviceExtension->VolumeParams.FsextControlCode) { FSP_FSEXT_PROVIDER *Provider = FspFsextProvider( - FsvolDeviceExtension->VolumeParams.FsextControlCode); + FsvolDeviceExtension->VolumeParams.FsextControlCode, 0); if (0 != Provider) Result = Provider->DeviceTransact(FsvolDeviceObject, Irp); } diff --git a/src/sys/fsext.c b/src/sys/fsext.c index 4f5ba307..b11a428f 100644 --- a/src/sys/fsext.c +++ b/src/sys/fsext.c @@ -25,7 +25,7 @@ static KSPIN_LOCK FsextSpinLock = 0; FSP_FSEXT_PROVIDER *FsextProvider; -FSP_FSEXT_PROVIDER *FspFsextProvider(UINT32 ControlCode) +FSP_FSEXT_PROVIDER *FspFsextProvider(UINT32 ControlCode, PNTSTATUS PLoadResult) { FSP_FSEXT_PROVIDER *Provider; KIRQL Irql; @@ -34,6 +34,61 @@ FSP_FSEXT_PROVIDER *FspFsextProvider(UINT32 ControlCode) Provider = FsextProvider; KeReleaseSpinLock(&FsextSpinLock, Irql); + if (0 != PLoadResult) + { + if (0 == Provider) + { + WCHAR Buf[64 + 256]; + UNICODE_STRING Path; + UNICODE_STRING Name; + union + { + KEY_VALUE_PARTIAL_INFORMATION V; + UINT8 B[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + 256]; + } Value; + ULONG Length; + NTSTATUS Result; + + RtlInitUnicodeString(&Path, L"" FSP_REGKEY "\\Fsext"); + RtlInitEmptyUnicodeString(&Name, Buf, sizeof Buf); + Result = RtlUnicodeStringPrintf(&Name, L"%08x", ControlCode); + ASSERT(NT_SUCCESS(Result)); + Length = sizeof Value; + Result = FspRegistryGetValue(&Path, &Name, &Value.V, &Length); + if (STATUS_SUCCESS != Result/*!NT_SUCCESS*/) + { + if (STATUS_BUFFER_OVERFLOW == Result) + Result = STATUS_BUFFER_TOO_SMALL; + + *PLoadResult = Result; + return 0; + } + if (REG_SZ != Value.V.Type) + { + *PLoadResult = STATUS_OBJECT_NAME_NOT_FOUND; + return 0; + } + + RtlInitEmptyUnicodeString(&Path, Buf, sizeof Buf); + Result = RtlUnicodeStringPrintf(&Path, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%s", Value.V.Data); + ASSERT(NT_SUCCESS(Result)); + + Result = ZwLoadDriver(&Path); + if (!NT_SUCCESS(Result) && STATUS_IMAGE_ALREADY_LOADED != Result) + { + *PLoadResult = Result; + return 0; + } + + KeAcquireSpinLock(&FsextSpinLock, &Irql); + Provider = FsextProvider; + KeReleaseSpinLock(&FsextSpinLock, Irql); + } + + *PLoadResult = 0 != Provider ? STATUS_SUCCESS : STATUS_OBJECT_NAME_NOT_FOUND; + } + return Provider; } @@ -43,14 +98,18 @@ NTSTATUS FspFsextProviderRegister(FSP_FSEXT_PROVIDER *Provider) KIRQL Irql; KeAcquireSpinLock(&FsextSpinLock, &Irql); + if (0 != FsextProvider) { Result = STATUS_TOO_LATE; goto exit; } + Provider->DeviceExtensionOffset = FIELD_OFFSET(FSP_FSVOL_DEVICE_EXTENSION, FsextData); FsextProvider = Provider; + Result = STATUS_SUCCESS; + exit: KeReleaseSpinLock(&FsextSpinLock, Irql);