dll: FspFileSystemSetMountPoint, FspFileSystemRemoveMountPoint

Ensure that mapped drives get cleaned up even if file system dies
This commit is contained in:
Bill Zissimopoulos 2016-06-22 23:16:22 -07:00
parent 3db09be764
commit b8b15e8035
4 changed files with 59 additions and 59 deletions

View File

@ -595,7 +595,7 @@ typedef struct _FSP_FILE_SYSTEM
ULONG DispatcherThreadCount; ULONG DispatcherThreadCount;
NTSTATUS DispatcherResult; NTSTATUS DispatcherResult;
PWSTR MountPoint; PWSTR MountPoint;
LIST_ENTRY MountEntry; HANDLE MountHandle;
UINT32 DebugLog; UINT32 DebugLog;
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy; FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy;
SRWLOCK OpGuardLock; SRWLOCK OpGuardLock;

View File

@ -25,60 +25,34 @@ enum
static FSP_FILE_SYSTEM_INTERFACE FspFileSystemNullInterface; static FSP_FILE_SYSTEM_INTERFACE FspFileSystemNullInterface;
static INIT_ONCE FspFileSystemInitOnce = INIT_ONCE_STATIC_INIT; static INIT_ONCE FspFileSystemInitOnce = INIT_ONCE_STATIC_INIT;
static BOOLEAN FspFileSystemInitialized; static NTSTATUS (NTAPI *FspNtOpenSymbolicLinkObject)(
static CRITICAL_SECTION FspFileSystemMountListGuard; PHANDLE LinkHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
static LIST_ENTRY FspFileSystemMountList = { &FspFileSystemMountList, &FspFileSystemMountList }; static NTSTATUS (NTAPI *FspNtMakeTemporaryObject)(
HANDLE Handle);
static NTSTATUS (NTAPI *FspNtClose)(
HANDLE Handle);
static BOOL WINAPI FspFileSystemInitialize( static BOOL WINAPI FspFileSystemInitialize(
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
{ {
InitializeCriticalSection(&FspFileSystemMountListGuard); HANDLE Handle;
return FspFileSystemInitialized = TRUE;
}
VOID FspFileSystemFinalize(BOOLEAN Dynamic) Handle = GetModuleHandleW(L"ntdll.dll");
{ if (0 != Handle)
/*
* This function is called during DLL_PROCESS_DETACH. We must therefore keep
* finalization tasks to a minimum.
*
* We enter our FspFileSystemMountListGuard critical section here and then attempt to cleanup
* our mount points using DefineDosDeviceW. On Vista and later orphaned critical sections
* become "electrified", so our process will be forcefully terminated if one of its threads
* was already modifying the list when the ExitProcess happened. This is a good thing!
*
* The use of DefineDosDeviceW is rather suspect and probably unsafe. DefineDosDeviceW reaches
* out to CSRSS, which is probably not the safest thing to do when in DllMain! There is also
* some evidence that it may attempt to load DLL's under some circumstances, which is a
* definite no-no as we are under the loader lock!
*
* We only delete the criticaly section when being dynamically unloaded. On process exit the
* OS will clean it up for us.
*/
if (!FspFileSystemInitialized)
return;
FSP_FILE_SYSTEM *FileSystem;
PLIST_ENTRY MountEntry;
EnterCriticalSection(&FspFileSystemMountListGuard);
for (MountEntry = FspFileSystemMountList.Flink;
&FspFileSystemMountList != MountEntry;
MountEntry = MountEntry->Flink)
{ {
FileSystem = CONTAINING_RECORD(MountEntry, FSP_FILE_SYSTEM, MountEntry); FspNtOpenSymbolicLinkObject = (PVOID)GetProcAddress(Handle, "NtOpenSymbolicLinkObject");
FspNtMakeTemporaryObject = (PVOID)GetProcAddress(Handle, "NtMakeTemporaryObject");
FspNtClose = (PVOID)GetProcAddress(Handle, "NtClose");
DefineDosDeviceW( if (0 == FspNtOpenSymbolicLinkObject || 0 == FspNtMakeTemporaryObject || 0 == FspNtClose)
DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, {
FileSystem->MountPoint, FileSystem->VolumeName); FspNtOpenSymbolicLinkObject = 0;
FspNtMakeTemporaryObject = 0;
FspNtClose = 0;
}
} }
LeaveCriticalSection(&FspFileSystemMountListGuard); return TRUE;
if (Dynamic)
DeleteCriticalSection(&FspFileSystemMountListGuard);
} }
FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath, FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
@ -95,8 +69,6 @@ FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
Interface = &FspFileSystemNullInterface; Interface = &FspFileSystemNullInterface;
InitOnceExecuteOnce(&FspFileSystemInitOnce, FspFileSystemInitialize, 0, 0); InitOnceExecuteOnce(&FspFileSystemInitOnce, FspFileSystemInitialize, 0, 0);
if (!FspFileSystemInitialized)
return STATUS_INSUFFICIENT_RESOURCES;
FileSystem = MemAlloc(sizeof *FileSystem); FileSystem = MemAlloc(sizeof *FileSystem);
if (0 == FileSystem) if (0 == FileSystem)
@ -151,6 +123,7 @@ FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR M
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
NTSTATUS Result; NTSTATUS Result;
HANDLE MountHandle = 0;
if (0 == MountPoint) if (0 == MountPoint)
{ {
@ -203,13 +176,41 @@ FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR M
} }
exit: exit:
if (NT_SUCCESS(Result) && 0 != FspNtOpenSymbolicLinkObject)
{
WCHAR SymlinkBuf[6];
UNICODE_STRING Symlink;
OBJECT_ATTRIBUTES Obja;
memcpy(SymlinkBuf, L"\\??\\X:", sizeof SymlinkBuf);
SymlinkBuf[4] = MountPoint[0];
Symlink.Length = Symlink.MaximumLength = sizeof SymlinkBuf;
Symlink.Buffer = SymlinkBuf;
memset(&Obja, 0, sizeof Obja);
Obja.Length = sizeof Obja;
Obja.ObjectName = &Symlink;
Obja.Attributes = OBJ_CASE_INSENSITIVE;
Result = FspNtOpenSymbolicLinkObject(&MountHandle, DELETE, &Obja);
if (NT_SUCCESS(Result))
{
Result = FspNtMakeTemporaryObject(MountHandle);
if (!NT_SUCCESS(Result))
{
FspNtClose(MountHandle);
MountHandle = 0;
}
}
/* this path always considered successful regardless if we made symlink temporary */
Result = STATUS_SUCCESS;
}
if (NT_SUCCESS(Result)) if (NT_SUCCESS(Result))
{ {
FileSystem->MountPoint = MountPoint; FileSystem->MountPoint = MountPoint;
FileSystem->MountHandle = MountHandle;
EnterCriticalSection(&FspFileSystemMountListGuard);
InsertTailList(&FspFileSystemMountList, &FileSystem->MountEntry);
LeaveCriticalSection(&FspFileSystemMountListGuard);
} }
else else
MemFree(MountPoint); MemFree(MountPoint);
@ -222,15 +223,16 @@ FSP_API VOID FspFileSystemRemoveMountPoint(FSP_FILE_SYSTEM *FileSystem)
if (0 == FileSystem->MountPoint) if (0 == FileSystem->MountPoint)
return; return;
EnterCriticalSection(&FspFileSystemMountListGuard);
RemoveEntryList(&FileSystem->MountEntry);
LeaveCriticalSection(&FspFileSystemMountListGuard);
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
FileSystem->MountPoint, FileSystem->VolumeName); FileSystem->MountPoint, FileSystem->VolumeName);
MemFree(FileSystem->MountPoint); MemFree(FileSystem->MountPoint);
FileSystem->MountPoint = 0; FileSystem->MountPoint = 0;
if (0 != FileSystem->MountHandle)
{
FspNtClose(FileSystem->MountHandle);
FileSystem->MountHandle = 0;
}
} }
static DWORD WINAPI FspFileSystemDispatcherThread(PVOID FileSystem0) static DWORD WINAPI FspFileSystemDispatcherThread(PVOID FileSystem0)

View File

@ -42,7 +42,6 @@ BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
Dynamic = 0 == Reserved; Dynamic = 0 == Reserved;
fsp_fuse_finalize(Dynamic); fsp_fuse_finalize(Dynamic);
FspServiceFinalize(Dynamic); FspServiceFinalize(Dynamic);
FspFileSystemFinalize(Dynamic);
FspEventLogFinalize(Dynamic); FspEventLogFinalize(Dynamic);
FspPosixFinalize(Dynamic); FspPosixFinalize(Dynamic);
break; break;

View File

@ -38,7 +38,6 @@
VOID FspPosixFinalize(BOOLEAN Dynamic); VOID FspPosixFinalize(BOOLEAN Dynamic);
VOID FspEventLogFinalize(BOOLEAN Dynamic); VOID FspEventLogFinalize(BOOLEAN Dynamic);
VOID FspFileSystemFinalize(BOOLEAN Dynamic);
VOID FspServiceFinalize(BOOLEAN Dynamic); VOID FspServiceFinalize(BOOLEAN Dynamic);
VOID fsp_fuse_finalize(BOOLEAN Dynamic); VOID fsp_fuse_finalize(BOOLEAN Dynamic);
VOID fsp_fuse_finalize_thread(VOID); VOID fsp_fuse_finalize_thread(VOID);