dll: use adaptive locks when starting/stopping FSD

This commit is contained in:
Bill Zissimopoulos 2023-12-12 12:36:41 +00:00
parent be5faf34bc
commit 65bf8c5319
3 changed files with 107 additions and 5 deletions

View File

@ -431,7 +431,23 @@ FSP_API NTSTATUS FspFsctlServiceVersion(PUINT32 PVersion)
return 0 != FspFsctlServiceVersionValue ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
static SRWLOCK FspFsctlStartStopServiceLock = SRWLOCK_INIT;
static FSP_ADAPTIVE_LOCK FspFsctlStartStopServiceLock = FSP_ADAPTIVE_LOCK_INIT;
static VOID FspFsctlStartStopServiceLockAcquire(VOID)
{
extern HINSTANCE DllInstance;
WCHAR DllPath[MAX_PATH];
PWSTR FileName = 0;
if (0 != GetModuleFileNameW(DllInstance, DllPath, MAX_PATH))
FileName = DllPath;
FspAdaptiveLockAcquire(&FspFsctlStartStopServiceLock,
FileName, 0xfffffffffffffff0ull, (10 + 1) * 1000);
}
static VOID FspFsctlStartStopServiceLockRelease(VOID)
{
FspAdaptiveLockRelease(&FspFsctlStartStopServiceLock);
}
static BOOLEAN FspFsctlRunningInContainer(VOID)
{
@ -455,7 +471,7 @@ static NTSTATUS FspFsctlStartServiceByName(PWSTR DriverName)
DWORD LastError;
NTSTATUS Result;
AcquireSRWLockExclusive(&FspFsctlStartStopServiceLock);
FspFsctlStartStopServiceLockAcquire();
if (FspFsctlRunningInContainer())
{
@ -517,7 +533,7 @@ exit:
if (0 != ScmHandle)
CloseServiceHandle(ScmHandle);
ReleaseSRWLockExclusive(&FspFsctlStartStopServiceLock);
FspFsctlStartStopServiceLockRelease();
return Result;
}
@ -587,7 +603,7 @@ FSP_API NTSTATUS FspFsctlStopService(VOID)
FspSxsAppendSuffix(DriverName, sizeof DriverName, L"" FSP_FSCTL_DRIVER_NAME);
AcquireSRWLockExclusive(&FspFsctlStartStopServiceLock);
FspFsctlStartStopServiceLockAcquire();
if (FspFsctlRunningInContainer())
{
@ -659,7 +675,7 @@ exit:
if (0 != ProcessToken)
CloseHandle(ProcessToken);
ReleaseSRWLockExclusive(&FspFsctlStartStopServiceLock);
FspFsctlStartStopServiceLockRelease();
return Result;
}

View File

@ -106,6 +106,21 @@ NTSTATUS FspGetModuleFileName(
ULONG Size,
PWSTR RelativePath);
typedef struct
{
SRWLOCK Lock;
HANDLE Handle;
UINT64 Offset;
} FSP_ADAPTIVE_LOCK;
#define FSP_ADAPTIVE_LOCK_INIT { SRWLOCK_INIT, INVALID_HANDLE_VALUE, 0 }
VOID FspAdaptiveLockAcquire(
FSP_ADAPTIVE_LOCK *Lock,
PWSTR FileName,
UINT64 Offset,
DWORD Timeout);
VOID FspAdaptiveLockRelease(
FSP_ADAPTIVE_LOCK *Lock);
#define FspFileSystemDirectoryBufferEntryInvalid ((ULONG)-1)
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
PUINT8 *PBuffer, PULONG *PIndex, PULONG PCount);

View File

@ -418,3 +418,74 @@ NTSTATUS FspGetModuleFileName(
return STATUS_SUCCESS;
}
VOID FspAdaptiveLockAcquire(
FSP_ADAPTIVE_LOCK *Lock,
PWSTR FileName,
UINT64 Offset,
DWORD Timeout)
{
AcquireSRWLockExclusive(&Lock->Lock);
if (0 != FileName)
{
HANDLE Handle;
DWORD BytesTransferred;
OVERLAPPED Overlapped;
BOOL Success;
Handle = CreateFileW(
FileName,
FILE_READ_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (INVALID_HANDLE_VALUE != Handle)
{
memset(&Overlapped, 0, sizeof Overlapped);
Overlapped.Offset = ((PLARGE_INTEGER)&Offset)->LowPart;
Overlapped.OffsetHigh = ((PLARGE_INTEGER)&Offset)->HighPart;
Success = LockFileEx(
Handle,
LOCKFILE_EXCLUSIVE_LOCK, 0,
1, 0,
&Overlapped);
if (Success || ERROR_IO_PENDING == GetLastError())
{
Success = FALSE;
if (WAIT_OBJECT_0 == WaitForSingleObject(Handle, Timeout))
Success = GetOverlappedResult(Handle, &Overlapped, &BytesTransferred, TRUE);
}
if (Success)
{
Lock->Handle = Handle;
Lock->Offset = Offset;
}
else
CloseHandle(Handle);
}
}
}
VOID FspAdaptiveLockRelease(
FSP_ADAPTIVE_LOCK *Lock)
{
if (INVALID_HANDLE_VALUE != Lock->Handle)
{
HANDLE Handle = Lock->Handle;
LARGE_INTEGER LargeOffset = *(PLARGE_INTEGER)&Lock->Offset;
UnlockFile(Handle, LargeOffset.LowPart, LargeOffset.HighPart, 1, 0);
CloseHandle(Handle);
Lock->Handle = INVALID_HANDLE_VALUE;
Lock->Offset = 0;
}
ReleaseSRWLockExclusive(&Lock->Lock);
}