sys,dll: FSP_FSCTL_UNLOAD

This commit is contained in:
Bill Zissimopoulos
2022-08-18 11:05:45 +01:00
parent 005d3e4fb0
commit 9670caa3fe
16 changed files with 445 additions and 69 deletions

View File

@ -30,6 +30,7 @@ NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
PDEVICE_OBJECT *PDeviceObject);
NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDoIoDeleteDevice(PDEVICE_OBJECT DeviceObject);
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
_IRQL_requires_(DISPATCH_LEVEL)
@ -67,13 +68,13 @@ NTSTATUS FspDeviceCopyList(
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
VOID FspDeviceDeleteList(
PDEVICE_OBJECT *DeviceObjects, ULONG DeviceObjectCount);
VOID FspDeviceDeleteAll(VOID);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspDeviceCreateSecure)
#pragma alloc_text(PAGE, FspDeviceCreate)
#pragma alloc_text(PAGE, FspDeviceInitialize)
#pragma alloc_text(PAGE, FspDeviceDelete)
#pragma alloc_text(PAGE, FspDeviceDoIoDeleteDevice)
#pragma alloc_text(PAGE, FspFsvolDeviceInit)
#pragma alloc_text(PAGE, FspFsvolDeviceFini)
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList)
@ -92,7 +93,6 @@ VOID FspDeviceDeleteAll(VOID);
#pragma alloc_text(PAGE, FspFsmupDeviceFini)
#pragma alloc_text(PAGE, FspDeviceCopyList)
#pragma alloc_text(PAGE, FspDeviceDeleteList)
#pragma alloc_text(PAGE, FspDeviceDeleteAll)
#endif
NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
@ -218,13 +218,23 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
return;
}
FspDeviceDoIoDeleteDevice(DeviceObject);
#if DBG
#pragma prefast(suppress:28175, "Debugging only: ok to access DeviceObject->Size")
RtlFillMemory(&DeviceExtension->Kind,
(PUINT8)DeviceObject + DeviceObject->Size - (PUINT8)&DeviceExtension->Kind, 0xBD);
#endif
}
IoDeleteDevice(DeviceObject);
VOID FspDeviceDoIoDeleteDevice(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
if (0 == InterlockedCompareExchange(&DeviceExtension->DidIoDeleteDevice, 1, 0))
IoDeleteDevice(DeviceObject);
}
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject)
@ -942,22 +952,4 @@ VOID FspDeviceDeleteList(
FspFree(DeviceObjects);
}
VOID FspDeviceDeleteAll(VOID)
{
PAGED_CODE();
NTSTATUS Result;
PDEVICE_OBJECT *DeviceObjects = 0;
ULONG DeviceObjectCount = 0;
Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount);
if (!NT_SUCCESS(Result))
return;
for (ULONG i = 0; DeviceObjectCount > i; i++)
FspDeviceDelete(DeviceObjects[i]);
FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
}
FAST_MUTEX FspDeviceGlobalMutex;

View File

@ -55,6 +55,7 @@ NTSTATUS FspDeviceInitializeAllTimers(VOID)
VOID FspDeviceFinalizeAllTimers(VOID)
{
KeCancelTimer(&FspDeviceTimer);
KeFlushQueuedDpcs();
#if DBG
KIRQL Irql;

View File

@ -21,27 +21,23 @@
#include <sys/driver.h>
/*
* Define the following macro to include FspUnload and make the driver unloadable.
*/
#define FSP_UNLOAD
DRIVER_INITIALIZE DriverEntry;
#if defined(FSP_UNLOAD)
DRIVER_UNLOAD FspUnload;
#endif
static DRIVER_UNLOAD DriverUnload;
static VOID FspDriverMultiVersionInitialize(VOID);
static NTSTATUS FspDriverInitializeDevices(VOID);
static VOID FspDriverFinalizeDevices(VOID);
static VOID FspDriverFinalizeDevicesEx(BOOLEAN DeleteDevices);
NTSTATUS FspDriverUnload(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#if defined(FSP_UNLOAD)
#pragma alloc_text(PAGE, FspUnload)
#endif
#pragma alloc_text(PAGE, DriverUnload)
#pragma alloc_text(INIT, FspDriverMultiVersionInitialize)
#pragma alloc_text(PAGE, FspDriverInitializeDevices)
#pragma alloc_text(PAGE, FspDriverFinalizeDevices)
#pragma alloc_text(PAGE, FspDriverFinalizeDevicesEx)
#pragma alloc_text(PAGE, FspDriverUnload)
#endif
NTSTATUS DriverEntry(
@ -54,9 +50,7 @@ NTSTATUS DriverEntry(
FspSxsIdentInitialize(&DriverObject->DriverName);
/* setup the driver object */
#if defined(FSP_UNLOAD)
DriverObject->DriverUnload = FspUnload;
#endif
DriverObject->DriverUnload = DriverUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose;
DriverObject->MajorFunction[IRP_MJ_READ] = FspRead;
@ -144,6 +138,7 @@ NTSTATUS DriverEntry(
FspDriverObject = DriverObject;
FspDriverMultiVersionInitialize();
ExInitializeFastMutex(&FspDriverUnloadMutex);
ExInitializeFastMutex(&FspDeviceGlobalMutex);
Result = FspSiloInitialize(FspDriverInitializeDevices, FspDriverFinalizeDevices);
@ -188,12 +183,13 @@ exit:
&DriverObject->DriverName, RegistryPath);
}
#if defined(FSP_UNLOAD)
VOID FspUnload(
VOID DriverUnload(
PDRIVER_OBJECT DriverObject)
{
FSP_ENTER_VOID(PAGED_CODE());
FspDriverFinalizeDevices();
FspDeviceFinalizeAllTimers();
FspProcessBufferFinalize();
@ -206,7 +202,6 @@ VOID FspUnload(
FSP_LEAVE_VOID("DriverName=\"%wZ\"",
&DriverObject->DriverName);
}
#endif
static VOID FspDriverMultiVersionInitialize(VOID)
{
@ -342,12 +337,25 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
* as a file system; we register with the MUP instead.
*/
IoRegisterFileSystem(Globals->FsctlDiskDeviceObject);
Globals->InitDoneRegisterDisk = 1;
/*
* Reference primary device objects to allow for IoDeleteDevice during FspDriverUnload.
*/
ObReferenceObject(Globals->FsctlDiskDeviceObject);
ObReferenceObject(Globals->FsctlNetDeviceObject);
ObReferenceObject(Globals->FsmupDeviceObject);
Result = STATUS_SUCCESS;
exit:
if (!NT_SUCCESS(Result))
{
if (Globals->InitDoneRegisterDisk)
{
IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject);
Globals->InitDoneRegisterDisk = 0;
}
if (0 != Globals->MupHandle)
{
FsRtlDeregisterUncProvider(Globals->MupHandle);
@ -391,14 +399,24 @@ static VOID FspDriverFinalizeDevices(VOID)
{
PAGED_CODE();
FspDriverFinalizeDevicesEx(TRUE);
}
static VOID FspDriverFinalizeDevicesEx(BOOLEAN DeleteDevices)
{
PAGED_CODE();
FSP_SILO_GLOBALS *Globals;
UNICODE_STRING SymlinkName;
FspSiloGetGlobals(&Globals);
ASSERT(0 != Globals);
IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject);
if (Globals->InitDoneRegisterDisk)
{
IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject);
Globals->InitDoneRegisterDisk = 0;
}
if (0 != Globals->MupHandle)
{
FsRtlDeregisterUncProvider(Globals->MupHandle);
@ -406,8 +424,14 @@ static VOID FspDriverFinalizeDevices(VOID)
}
if (0 != Globals->FsmupDeviceObject)
{
FspDeviceDelete(Globals->FsmupDeviceObject);
Globals->FsmupDeviceObject = 0;
if (DeleteDevices)
{
FspDeviceDelete(Globals->FsmupDeviceObject);
ObDereferenceObject(Globals->FsmupDeviceObject);
Globals->FsmupDeviceObject = 0;
}
else
FspDeviceDoIoDeleteDevice(Globals->FsmupDeviceObject);
}
if (Globals->InitDoneSymlinkNet)
{
@ -417,8 +441,14 @@ static VOID FspDriverFinalizeDevices(VOID)
}
if (0 != Globals->FsctlNetDeviceObject)
{
FspDeviceDelete(Globals->FsctlNetDeviceObject);
Globals->FsctlNetDeviceObject = 0;
if (DeleteDevices)
{
FspDeviceDelete(Globals->FsctlNetDeviceObject);
ObDereferenceObject(Globals->FsctlNetDeviceObject);
Globals->FsctlNetDeviceObject = 0;
}
else
FspDeviceDoIoDeleteDevice(Globals->FsctlNetDeviceObject);
}
if (Globals->InitDoneSymlinkDisk)
{
@ -428,16 +458,84 @@ static VOID FspDriverFinalizeDevices(VOID)
}
if (0 != Globals->FsctlDiskDeviceObject)
{
FspDeviceDelete(Globals->FsctlDiskDeviceObject);
Globals->FsctlDiskDeviceObject = 0;
if (DeleteDevices)
{
FspDeviceDelete(Globals->FsctlDiskDeviceObject);
ObDereferenceObject(Globals->FsctlDiskDeviceObject);
Globals->FsctlDiskDeviceObject = 0;
}
else
FspDeviceDoIoDeleteDevice(Globals->FsctlDiskDeviceObject);
}
FspSiloDereferenceGlobals(Globals);
}
NTSTATUS FspDriverUnload(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
ASSERT(FSP_FSCTL_UNLOAD == IrpSp->Parameters.FileSystemControl.FsControlCode);
NTSTATUS Result;
UNICODE_STRING DriverServiceName, DriverName, Remain;
WCHAR DriverServiceNameBuf[64 + 256];
PDEVICE_OBJECT *DeviceObjects = 0;
ULONG DeviceObjectCount = 0;
if (!FspSiloIsHost())
return STATUS_INVALID_DEVICE_REQUEST;
if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_LOAD_DRIVER_PRIVILEGE), UserMode))
return STATUS_PRIVILEGE_NOT_HELD;
ExAcquireFastMutexUnsafe(&FspDriverUnloadMutex);
if (!FspDriverUnloadDone)
{
FspFileNameSuffix(&FspDriverObject->DriverName, &Remain, &DriverName);
RtlInitEmptyUnicodeString(&DriverServiceName, DriverServiceNameBuf, sizeof DriverServiceNameBuf);
Result = RtlUnicodeStringPrintf(&DriverServiceName,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%wZ", &DriverName);
if (!NT_SUCCESS(Result))
goto exit;
Result = ZwUnloadDriver(&DriverServiceName);
if (!NT_SUCCESS(Result))
goto exit;
FspDriverFinalizeDevicesEx(FALSE);
Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount);
if (NT_SUCCESS(Result))
{
for (ULONG I = 0; DeviceObjectCount > I; I++)
{
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObjects[I]);
if (FspFsvolDeviceExtensionKind == DeviceExtension->Kind)
FspIoqStop(((FSP_FSVOL_DEVICE_EXTENSION *)DeviceExtension)->Ioq, FALSE);
}
FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
}
FspDriverUnloadDone = TRUE;
}
Result = STATUS_SUCCESS;
exit:
ExReleaseFastMutexUnsafe(&FspDriverUnloadMutex);
return Result;
}
PDRIVER_OBJECT FspDriverObject;
FAST_IO_DISPATCH FspFastIoDispatch;
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
FAST_MUTEX FspDriverUnloadMutex;
BOOLEAN FspDriverUnloadDone;
ULONG FspProcessorCount;
FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;

View File

@ -364,6 +364,10 @@ VOID FspTraceNtStatus(const char *file, int line, const char *func, NTSTATUS Sta
/* missing typedef */
typedef const void *PCVOID;
/* driver unload */
NTSTATUS FspDriverUnload(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
/* driver major functions */
_Function_class_(DRIVER_DISPATCH)
_IRQL_requires_max_(APC_LEVEL)
@ -752,10 +756,11 @@ typedef struct
PDEVICE_OBJECT FsmupDeviceObject;
HANDLE MupHandle;
WCHAR FsmupDeviceNameBuf[128];
UINT32 InitDoneSymlinkDisk:1, InitDoneSymlinkNet:1;
UINT32 InitDoneSymlinkDisk:1, InitDoneSymlinkNet:1, InitDoneRegisterDisk:1;
} FSP_SILO_GLOBALS;
typedef NTSTATUS (*FSP_SILO_INIT_CALLBACK)(VOID);
typedef VOID (*FSP_SILO_FINI_CALLBACK)(VOID);
BOOLEAN FspSiloIsHost(VOID);
NTSTATUS FspSiloGetGlobals(FSP_SILO_GLOBALS **PGlobals);
VOID FspSiloDereferenceGlobals(FSP_SILO_GLOBALS *Globals);
VOID FspSiloGetContainerId(GUID *ContainerId);
@ -1188,8 +1193,8 @@ typedef struct
LONG RefCount;
UINT32 Kind;
GUID SiloContainerId;
/* IoTimer emulation */
FSP_DEVICE_TIMER DeviceTimer;
FSP_DEVICE_TIMER DeviceTimer; /* IoTimer emulation */
LONG DidIoDeleteDevice;
} FSP_DEVICE_EXTENSION;
typedef struct
{
@ -1291,6 +1296,7 @@ NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
PDEVICE_OBJECT *PDeviceObject);
NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDoIoDeleteDevice(PDEVICE_OBJECT DeviceObject);
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
static inline
@ -1473,7 +1479,6 @@ NTSTATUS FspDeviceCopyList(
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
VOID FspDeviceDeleteList(
PDEVICE_OBJECT *DeviceObjects, ULONG DeviceObjectCount);
VOID FspDeviceDeleteAll(VOID);
NTSTATUS FspDeviceInitializeAllTimers(VOID);
VOID FspDeviceFinalizeAllTimers(VOID);
NTSTATUS FspDeviceInitializeTimer(PDEVICE_OBJECT DeviceObject,
@ -2005,6 +2010,8 @@ FSP_MV_CcCoherencyFlushAndPurgeCache(
extern PDRIVER_OBJECT FspDriverObject;
extern FAST_IO_DISPATCH FspFastIoDispatch;
extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
extern FAST_MUTEX FspDriverUnloadMutex;
extern BOOLEAN FspDriverUnloadDone;
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
extern FAST_MUTEX FspDeviceGlobalMutex;

View File

@ -128,6 +128,9 @@ static NTSTATUS FspFsctlFileSystemControl(
if (0 != IrpSp->FileObject->FsContext2)
Result = FspVolumeNotify(FsctlDeviceObject, Irp, IrpSp);
break;
case FSP_FSCTL_UNLOAD:
Result = FspDriverUnload(FsctlDeviceObject, Irp, IrpSp);
break;
default:
if (CTL_CODE(0, 0xC00, 0, 0) ==
(IrpSp->Parameters.FileSystemControl.FsControlCode & CTL_CODE(0, 0xC00, 0, 0)))

View File

@ -123,6 +123,27 @@ NTSTATUS FspProcessBufferInitialize(VOID)
VOID FspProcessBufferFinalize(VOID)
{
PsSetCreateProcessNotifyRoutine(FspProcessBufferNotifyRoutine, TRUE);
/*
* Free any items in our process hash table.
* Any virtual memory was released when the corresponding processes went away.
*/
for (ULONG HashIndex = 0; ProcessBufferBucketCount > HashIndex; HashIndex++)
{
for (FSP_PROCESS_BUFFER_ITEM *Item = ProcessBufferBuckets[HashIndex], *DictNext; Item; Item = DictNext)
{
for (FSP_PROCESS_BUFFER_LIST_ENTRY *P = Item->BufferList, *Next; P; P = Next)
{
Next = P->Next;
FspFree(P);
}
DictNext = Item->DictNext;
FspFree(Item);
}
ProcessBufferBuckets[HashIndex] = 0;
}
}
static VOID FspProcessBufferNotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)

View File

@ -123,6 +123,11 @@ static FSP_SILO_GLOBALS FspSiloHostGlobals;
}
#define CALL(n) (FspSilo ## n)
BOOLEAN FspSiloIsHost(VOID)
{
return !FspSiloInitDone || 0 == CALL(PsGetCurrentServerSilo)();
}
NTSTATUS FspSiloGetGlobals(FSP_SILO_GLOBALS **PGlobals)
{
FSP_PESILO Silo;