From 5d26211c38c3464d93d9a6bcd5faefed3b42bcc4 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Wed, 10 Feb 2016 11:37:28 -0800 Subject: [PATCH] sys: FspUnicodePathIsValid() --- src/sys/driver.h | 1 + src/sys/fileinfo.c | 10 ++++++++++ src/sys/util.c | 29 ++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/sys/driver.h b/src/sys/driver.h index 7ad3d42e..56454152 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -338,6 +338,7 @@ ULONG FspHashMixPointer(PVOID Pointer) /* utility */ PVOID FspAllocMustSucceed(SIZE_T Size); PVOID FspAllocateIrpMustSucceed(CCHAR StackSize); +BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams); VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix); NTSTATUS FspCreateGuid(GUID *Guid); NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes); diff --git a/src/sys/fileinfo.c b/src/sys/fileinfo.c index f98a7b3b..bf03699c 100644 --- a/src/sys/fileinfo.c +++ b/src/sys/fileinfo.c @@ -809,6 +809,9 @@ static NTSTATUS FspFsvolSetRenameInformation( if (FileNode->IsRootDirectory) /* cannot rename root directory */ return STATUS_INVALID_PARAMETER; + if (!FspUnicodePathIsValid(&FileNode->FileName, FALSE)) + /* cannot rename streams (WinFsp limitation) */ + return STATUS_INVALID_PARAMETER; if (0 != TargetFileNode) { @@ -831,6 +834,13 @@ static NTSTATUS FspFsvolSetRenameInformation( if (L'\\' == Suffix.Buffer[0]) FspUnicodePathSuffix(&Suffix, &NewFileName, &Suffix); + if (!FspUnicodePathIsValid(&Remain, FALSE) || !FspUnicodePathIsValid(&Suffix, FALSE)) + { + /* cannot rename streams (WinFsp limitation) */ + Result = STATUS_INVALID_PARAMETER; + goto unlock_exit; + } + AppendBackslash = sizeof(WCHAR) < Remain.Length; NewFileName.Length = NewFileName.MaximumLength = Remain.Length + AppendBackslash * sizeof(WCHAR) + Suffix.Length; diff --git a/src/sys/util.c b/src/sys/util.c index ee95dede..99dfeda6 100644 --- a/src/sys/util.c +++ b/src/sys/util.c @@ -6,6 +6,7 @@ #include +BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams); VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix); NTSTATUS FspCreateGuid(GUID *Guid); VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem, @@ -18,6 +19,7 @@ VOID FspQueueDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem, LARGE_INTEG static KDEFERRED_ROUTINE FspQueueDelayedWorkItemDPC; #ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FspUnicodePathIsValid) #pragma alloc_text(PAGE, FspUnicodePathSuffix) #pragma alloc_text(PAGE, FspCreateGuid) #pragma alloc_text(PAGE, FspInitializeSynchronousWorkItem) @@ -69,6 +71,31 @@ PVOID FspAllocateIrpMustSucceed(CCHAR StackSize) } } +BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams) +{ + PAGED_CODE(); + + PWSTR PathBgn, PathEnd, PathPtr; + + PathBgn = Path->Buffer; + PathEnd = (PWSTR)((PUINT8)PathBgn + Path->Length); + PathPtr = PathBgn; + + while (PathEnd > PathPtr) + if (L'\\' == *PathPtr) + { + PathPtr++; + if (PathEnd > PathPtr && L'\\' == *PathPtr) + return FALSE; + } + else if (!AllowStreams && L':' == *PathPtr) + return FALSE; + else + PathPtr++; + + return TRUE; +} + VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix) { PAGED_CODE(); @@ -86,7 +113,7 @@ VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE if (L'\\' == *PathPtr) { RemainEnd = PathPtr++; - for (; L'\\' == *PathPtr; PathPtr++) + for (; PathEnd > PathPtr && L'\\' == *PathPtr; PathPtr++) ; SuffixBgn = PathPtr; }