sys: check and remove volume prefix when mounted as a network file system

This commit is contained in:
Bill Zissimopoulos 2016-01-21 15:06:41 -08:00
parent e8eccef80a
commit e2e96322f3
6 changed files with 54 additions and 33 deletions

View File

@ -169,12 +169,13 @@ static NTSTATUS FspFsvolCreate(
/* check for trailing backslash */ /* check for trailing backslash */
if (sizeof(WCHAR) * 2/* not empty or root */ <= FileName.Length && if (sizeof(WCHAR) * 2/* not empty or root */ <= FileName.Length &&
L'\\' == FileName.Buffer[FileName.Length / 2 - 1]) L'\\' == FileName.Buffer[FileName.Length / sizeof(WCHAR) - 1])
{ {
FileName.Length -= sizeof(WCHAR); FileName.Length -= sizeof(WCHAR);
HasTrailingBackslash = TRUE; HasTrailingBackslash = TRUE;
if (sizeof(WCHAR) * 2 <= FileName.Length && L'\\' == FileName.Buffer[FileName.Length / 2 - 1]) if (sizeof(WCHAR) * 2 <= FileName.Length &&
L'\\' == FileName.Buffer[FileName.Length / sizeof(WCHAR) - 1])
return STATUS_OBJECT_NAME_INVALID; return STATUS_OBJECT_NAME_INVALID;
} }
if (HasTrailingBackslash && !FlagOn(CreateOptions, FILE_DIRECTORY_FILE)) if (HasTrailingBackslash && !FlagOn(CreateOptions, FILE_DIRECTORY_FILE))
@ -260,6 +261,23 @@ static NTSTATUS FspFsvolCreate(
Result = RtlAppendUnicodeStringToString(&FileNode->FileName, &FileName); Result = RtlAppendUnicodeStringToString(&FileNode->FileName, &FileName);
ASSERT(NT_SUCCESS(Result)); ASSERT(NT_SUCCESS(Result));
/* check and remove any volume prefix */
if (0 < FsvolDeviceExtension->VolumePrefix.Length)
{
if (FileNode->FileName.Length <= FsvolDeviceExtension->VolumePrefix.Length ||
!RtlEqualMemory(FileNode->FileName.Buffer, FsvolDeviceExtension->VolumePrefix.Buffer,
FsvolDeviceExtension->VolumePrefix.Length) ||
'\\' != FileNode->FileName.Buffer[FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR)])
{
FspFileNodeDereference(FileNode);
return STATUS_OBJECT_PATH_NOT_FOUND;
}
FileNode->FileName.Length -= FsvolDeviceExtension->VolumePrefix.Length;
FileNode->FileName.MaximumLength -= FsvolDeviceExtension->VolumePrefix.Length;
FileNode->FileName.Buffer += FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR);
}
Result = FspFileDescCreate(&FileDesc); Result = FspFileDescCreate(&FileDesc);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {

View File

@ -451,6 +451,7 @@ typedef struct
FSP_DELAYED_WORK_ITEM DeleteVolumeDelayedWorkItem; FSP_DELAYED_WORK_ITEM DeleteVolumeDelayedWorkItem;
ERESOURCE DeleteResource; ERESOURCE DeleteResource;
FSP_FSCTL_VOLUME_PARAMS VolumeParams; FSP_FSCTL_VOLUME_PARAMS VolumeParams;
UNICODE_STRING VolumePrefix;
FSP_IOQ *Ioq; FSP_IOQ *Ioq;
KSPIN_LOCK ExpirationLock; KSPIN_LOCK ExpirationLock;
WORK_QUEUE_ITEM ExpirationWorkItem; WORK_QUEUE_ITEM ExpirationWorkItem;

View File

@ -102,7 +102,7 @@ NTSTATUS FspVolumeCreate(
VolumeParams.IrpCapacity = FspFsctlIrpCapacityDefault; VolumeParams.IrpCapacity = FspFsctlIrpCapacityDefault;
if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType) if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType)
{ {
VolumeParams.Prefix[sizeof VolumeParams.Prefix / 2 - 1] = L'\0'; VolumeParams.Prefix[sizeof VolumeParams.Prefix / sizeof(WCHAR) - 1] = L'\0';
for (; L'\0' != VolumeParams.Prefix[PrefixLength]; PrefixLength++) for (; L'\0' != VolumeParams.Prefix[PrefixLength]; PrefixLength++)
; ;
for (; 0 < PrefixLength && L'\\' == VolumeParams.Prefix[PrefixLength - 1]; PrefixLength--) for (; 0 < PrefixLength && L'\\' == VolumeParams.Prefix[PrefixLength - 1]; PrefixLength--)
@ -155,6 +155,9 @@ NTSTATUS FspVolumeCreate(
FsvolDeviceExtension->FsctlDeviceObject = FsctlDeviceObject; FsvolDeviceExtension->FsctlDeviceObject = FsctlDeviceObject;
FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject; FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject;
FsvolDeviceExtension->VolumeParams = VolumeParams; FsvolDeviceExtension->VolumeParams = VolumeParams;
if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType)
RtlInitUnicodeString(&FsvolDeviceExtension->VolumePrefix,
FsvolDeviceExtension->VolumeParams.Prefix);
RtlInitEmptyUnicodeString(&FsvolDeviceExtension->VolumeName, RtlInitEmptyUnicodeString(&FsvolDeviceExtension->VolumeName,
FsvolDeviceExtension->VolumeNameBuf, sizeof FsvolDeviceExtension->VolumeNameBuf); FsvolDeviceExtension->VolumeNameBuf, sizeof FsvolDeviceExtension->VolumeNameBuf);
RtlCopyUnicodeString(&FsvolDeviceExtension->VolumeName, &VolumeName); RtlCopyUnicodeString(&FsvolDeviceExtension->VolumeName, &VolumeName);
@ -424,7 +427,6 @@ NTSTATUS FspVolumeRedirQueryPathEx(
NTSTATUS Result; NTSTATUS Result;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
UNICODE_STRING Prefix;
/* acquire our DeleteResource */ /* acquire our DeleteResource */
ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->DeleteResource, TRUE); ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->DeleteResource, TRUE);
@ -432,13 +434,14 @@ NTSTATUS FspVolumeRedirQueryPathEx(
Result = STATUS_BAD_NETWORK_PATH; Result = STATUS_BAD_NETWORK_PATH;
if (!FspIoqStopped(FsvolDeviceExtension->Ioq)) if (!FspIoqStopped(FsvolDeviceExtension->Ioq))
{ {
RtlInitUnicodeString(&Prefix, FsvolDeviceExtension->VolumeParams.Prefix); if (0 < FsvolDeviceExtension->VolumePrefix.Length &&
if (Prefix.Length <= QueryPathRequest->PathName.Length && QueryPathRequest->PathName.Length >= FsvolDeviceExtension->VolumePrefix.Length &&
RtlEqualMemory(Prefix.Buffer, QueryPathRequest->PathName.Buffer, Prefix.Length) && RtlEqualMemory(QueryPathRequest->PathName.Buffer,
(Prefix.Length == QueryPathRequest->PathName.Length || FsvolDeviceExtension->VolumePrefix.Buffer, FsvolDeviceExtension->VolumePrefix.Length) &&
'\\' == QueryPathRequest->PathName.Buffer[Prefix.Length / 2])) (QueryPathRequest->PathName.Length == FsvolDeviceExtension->VolumePrefix.Length ||
'\\' == QueryPathRequest->PathName.Buffer[FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR)]))
{ {
QueryPathResponse->LengthAccepted = Prefix.Length; QueryPathResponse->LengthAccepted = FsvolDeviceExtension->VolumePrefix.Length;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
Result = STATUS_SUCCESS; Result = STATUS_SUCCESS;

View File

@ -107,7 +107,7 @@ void create_test(void)
{ {
if (WinFspDiskTests) if (WinFspDiskTests)
create_dotest(MemfsDisk, 0); create_dotest(MemfsDisk, 0);
if (0 && WinFspNetTests) if (WinFspNetTests)
create_dotest(MemfsNet, L"\\\\memfs\\share"); create_dotest(MemfsNet, L"\\\\memfs\\share");
} }
@ -211,7 +211,7 @@ void create_sd_test(void)
{ {
if (WinFspDiskTests) if (WinFspDiskTests)
create_sd_dotest(MemfsDisk, 0); create_sd_dotest(MemfsDisk, 0);
if (0 && WinFspNetTests) if (WinFspNetTests)
create_sd_dotest(MemfsNet, L"\\\\memfs\\share"); create_sd_dotest(MemfsNet, L"\\\\memfs\\share");
} }
@ -279,7 +279,7 @@ void create_share_test(void)
{ {
if (WinFspDiskTests) if (WinFspDiskTests)
create_share_dotest(MemfsDisk, 0); create_share_dotest(MemfsDisk, 0);
if (0 && WinFspNetTests) if (WinFspNetTests)
create_share_dotest(MemfsNet, L"\\\\memfs\\share"); create_share_dotest(MemfsNet, L"\\\\memfs\\share");
} }

View File

@ -87,7 +87,7 @@ static unsigned __stdcall mount_volume_cancel_dotest_thread(void *FilePath)
return 0; return 0;
} }
void mount_volume_cancel_dotest(PWSTR DeviceName) void mount_volume_cancel_dotest(PWSTR DeviceName, PWSTR Prefix)
{ {
NTSTATUS Result; NTSTATUS Result;
BOOL Success; BOOL Success;
@ -107,11 +107,12 @@ void mount_volume_cancel_dotest(PWSTR DeviceName)
ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15)); ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15));
ASSERT(INVALID_HANDLE_VALUE != VolumeHandle); ASSERT(INVALID_HANDLE_VALUE != VolumeHandle);
StringCbPrintfW(FilePath, sizeof FilePath, L"\\\\?\\GLOBALROOT%s\\file0", VolumeName); StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : VolumeName);
Thread = (HANDLE)_beginthreadex(0, 0, mount_volume_cancel_dotest_thread, FilePath, 0, 0); Thread = (HANDLE)_beginthreadex(0, 0, mount_volume_cancel_dotest_thread, FilePath, 0, 0);
ASSERT(0 != Thread); ASSERT(0 != Thread);
Sleep(1000); /* give some time to the thread to execute */ Sleep(0 == Prefix ? 1000 : 5000); /* give some time to the thread to execute */
Success = CloseHandle(VolumeHandle); Success = CloseHandle(VolumeHandle);
ASSERT(Success); ASSERT(Success);
@ -126,9 +127,9 @@ void mount_volume_cancel_dotest(PWSTR DeviceName)
void mount_volume_cancel_test(void) void mount_volume_cancel_test(void)
{ {
if (WinFspDiskTests) if (WinFspDiskTests)
mount_volume_cancel_dotest(L"WinFsp.Disk"); mount_volume_cancel_dotest(L"WinFsp.Disk", 0);
if (WinFspNetTests) if (WinFspNetTests)
mount_volume_cancel_dotest(L"WinFsp.Net"); mount_volume_cancel_dotest(L"WinFsp.Net", L"\\\\winfsp-tests\\share");
} }
static unsigned __stdcall mount_volume_transact_dotest_thread(void *FilePath) static unsigned __stdcall mount_volume_transact_dotest_thread(void *FilePath)
@ -210,9 +211,7 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
ASSERT(!Request->Req.Create.CaseSensitive); ASSERT(!Request->Req.Create.CaseSensitive);
ASSERT(0 == Request->FileName.Offset); ASSERT(0 == Request->FileName.Offset);
ASSERT((wcslen((PVOID)Request->Buffer) + 1) * sizeof(WCHAR) == Request->FileName.Size); ASSERT((wcslen((PVOID)Request->Buffer) + 1) * sizeof(WCHAR) == Request->FileName.Size);
ASSERT( ASSERT(0 == wcscmp((PVOID)Request->Buffer, L"\\file0"));
0 == wcscmp((PVOID)Request->Buffer, L"\\file0") ||
0 == wcscmp((PVOID)Request->Buffer, FilePath + 1));
ASSERT(FspFsctlTransactCanProduceResponse(Response, ResponseBufEnd)); ASSERT(FspFsctlTransactCanProduceResponse(Response, ResponseBufEnd));
@ -250,10 +249,7 @@ void mount_volume_transact_test(void)
if (WinFspDiskTests) if (WinFspDiskTests)
mount_volume_transact_dotest(L"WinFsp.Disk", 0); mount_volume_transact_dotest(L"WinFsp.Disk", 0);
if (WinFspNetTests) if (WinFspNetTests)
{
mount_volume_transact_dotest(L"WinFsp.Net", 0);
mount_volume_transact_dotest(L"WinFsp.Net", L"\\\\winfsp-tests\\share"); mount_volume_transact_dotest(L"WinFsp.Net", L"\\\\winfsp-tests\\share");
}
} }
void mount_tests(void) void mount_tests(void)

View File

@ -34,7 +34,7 @@ static unsigned __stdcall timeout_pending_dotest_thread2(void *FilePath)
return 0; return 0;
} }
void timeout_pending_dotest(PWSTR DeviceName) void timeout_pending_dotest(PWSTR DeviceName, PWSTR Prefix)
{ {
NTSTATUS Result; NTSTATUS Result;
BOOL Success; BOOL Success;
@ -45,6 +45,7 @@ void timeout_pending_dotest(PWSTR DeviceName)
HANDLE Thread; HANDLE Thread;
DWORD ExitCode; DWORD ExitCode;
VolumeParams.TransactTimeout = 10000; /* allow for longer transact timeout to handle MUP redir */
VolumeParams.IrpTimeout = FspFsctlIrpTimeoutDebug; VolumeParams.IrpTimeout = FspFsctlIrpTimeoutDebug;
VolumeParams.SectorSize = 16384; VolumeParams.SectorSize = 16384;
VolumeParams.SerialNumber = 0x12345678; VolumeParams.SerialNumber = 0x12345678;
@ -55,7 +56,8 @@ void timeout_pending_dotest(PWSTR DeviceName)
ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15)); ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15));
ASSERT(INVALID_HANDLE_VALUE != VolumeHandle); ASSERT(INVALID_HANDLE_VALUE != VolumeHandle);
StringCbPrintfW(FilePath, sizeof FilePath, L"\\\\?\\GLOBALROOT%s\\file0", VolumeName); StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : VolumeName);
Thread = (HANDLE)_beginthreadex(0, 0, timeout_pending_dotest_thread, FilePath, 0, 0); Thread = (HANDLE)_beginthreadex(0, 0, timeout_pending_dotest_thread, FilePath, 0, 0);
ASSERT(0 != Thread); ASSERT(0 != Thread);
@ -126,9 +128,9 @@ void timeout_pending_dotest(PWSTR DeviceName)
void timeout_pending_test(void) void timeout_pending_test(void)
{ {
if (WinFspDiskTests) if (WinFspDiskTests)
timeout_pending_dotest(L"WinFsp.Disk"); timeout_pending_dotest(L"WinFsp.Disk", 0);
if (WinFspNetTests) if (WinFspNetTests)
timeout_pending_dotest(L"WinFsp.Net"); timeout_pending_dotest(L"WinFsp.Net", L"\\\\winfsp-tests\\share");
} }
static unsigned __stdcall timeout_transact_dotest_thread(void *FilePath) static unsigned __stdcall timeout_transact_dotest_thread(void *FilePath)
@ -144,7 +146,7 @@ static unsigned __stdcall timeout_transact_dotest_thread(void *FilePath)
return 0; return 0;
} }
void timeout_transact_dotest(PWSTR DeviceName) void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
{ {
NTSTATUS Result; NTSTATUS Result;
BOOL Success; BOOL Success;
@ -155,7 +157,7 @@ void timeout_transact_dotest(PWSTR DeviceName)
HANDLE Thread; HANDLE Thread;
DWORD ExitCode; DWORD ExitCode;
VolumeParams.TransactTimeout = 1000; VolumeParams.TransactTimeout = 0 != Prefix ? 1000 : 5000;
VolumeParams.SectorSize = 16384; VolumeParams.SectorSize = 16384;
VolumeParams.SerialNumber = 0x12345678; VolumeParams.SerialNumber = 0x12345678;
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), L"\\winfsp-tests\\share"); wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), L"\\winfsp-tests\\share");
@ -181,7 +183,8 @@ void timeout_transact_dotest(PWSTR DeviceName)
ASSERT(STATUS_SUCCESS == Result); ASSERT(STATUS_SUCCESS == Result);
ASSERT(0 == RequestBufSize); ASSERT(0 == RequestBufSize);
StringCbPrintfW(FilePath, sizeof FilePath, L"\\\\?\\GLOBALROOT%s\\file0", VolumeName); StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : VolumeName);
Thread = (HANDLE)_beginthreadex(0, 0, timeout_transact_dotest_thread, FilePath, 0, 0); Thread = (HANDLE)_beginthreadex(0, 0, timeout_transact_dotest_thread, FilePath, 0, 0);
ASSERT(0 != Thread); ASSERT(0 != Thread);
@ -232,9 +235,9 @@ void timeout_transact_dotest(PWSTR DeviceName)
void timeout_transact_test(void) void timeout_transact_test(void)
{ {
if (WinFspDiskTests) if (WinFspDiskTests)
timeout_transact_dotest(L"WinFsp.Disk"); timeout_transact_dotest(L"WinFsp.Disk", 0);
if (WinFspNetTests) if (WinFspNetTests)
timeout_transact_dotest(L"WinFsp.Net"); timeout_transact_dotest(L"WinFsp.Net", L"\\\\winfsp-tests\\share");
} }
void timeout_tests(void) void timeout_tests(void)