From d8bb5bf97628bbc34fb99b7e15a63a52f6ed44ac Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Wed, 10 Feb 2016 12:05:53 -0800 Subject: [PATCH] sys: IRP_MJ_CREATE: FileName validation and other checks --- src/sys/create.c | 70 +++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/src/sys/create.c b/src/sys/create.c index 6ff96246..a6299b00 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -153,7 +153,6 @@ static NTSTATUS FspFsvolCreateNoLock( FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode; BOOLEAN HasTraversePrivilege = BooleanFlagOn(AccessState->Flags, TOKEN_HAS_TRAVERSE_PRIVILEGE); - BOOLEAN HasTrailingBackslash = FALSE; FSP_FILE_NODE *FileNode, *RelatedFileNode; FSP_FILE_DESC *FileDesc; FSP_FSCTL_TRANSACT_REQ *Request; @@ -195,12 +194,12 @@ static NTSTATUS FspFsvolCreateNoLock( FileName.Length -= sizeof(WCHAR); FileName.MaximumLength -= sizeof(WCHAR); FileName.Buffer++; - - if (sizeof(WCHAR) * 2 <= FileName.Length && - L'\\' == FileName.Buffer[1] && L'\\' == FileName.Buffer[0]) - return STATUS_OBJECT_NAME_INVALID; } + /* check filename validity */ + if (!FspUnicodePathIsValid(&FileName, 0 != FsvolDeviceExtension->VolumeParams.NamedStreams)) + return STATUS_OBJECT_NAME_INVALID; + /* is this a relative or absolute open? */ if (0 != RelatedFileObject) { @@ -219,20 +218,6 @@ static NTSTATUS FspFsvolCreateNoLock( if (sizeof(WCHAR) <= FileName.Length && L'\\' == FileName.Buffer[0]) return STATUS_OBJECT_NAME_INVALID; - /* not all operations allowed on the root directory */ - if ((FILE_CREATE == CreateDisposition || - FILE_OVERWRITE == CreateDisposition || - FILE_OVERWRITE_IF == CreateDisposition || - FILE_SUPERSEDE == CreateDisposition || - BooleanFlagOn(Flags, SL_OPEN_TARGET_DIRECTORY)) && - sizeof(WCHAR) == RelatedFileNode->FileName.Length && 0 == FileName.Length) - return STATUS_ACCESS_DENIED; - - /* cannot FILE_DELETE_ON_CLOSE on the root directory */ - if (FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE) && - sizeof(WCHAR) == RelatedFileNode->FileName.Length && 0 == FileName.Length) - return STATUS_CANNOT_DELETE; - BOOLEAN AppendBackslash = sizeof(WCHAR) * 2/* not empty or root */ <= RelatedFileNode->FileName.Length && sizeof(WCHAR) <= FileName.Length && L':' != FileName.Buffer[0]; @@ -256,20 +241,6 @@ static NTSTATUS FspFsvolCreateNoLock( if (sizeof(WCHAR) <= FileName.Length && L'\\' != FileName.Buffer[0]) return STATUS_OBJECT_NAME_INVALID; - /* not all operations allowed on the root directory */ - if ((FILE_CREATE == CreateDisposition || - FILE_OVERWRITE == CreateDisposition || - FILE_OVERWRITE_IF == CreateDisposition || - FILE_SUPERSEDE == CreateDisposition || - BooleanFlagOn(Flags, SL_OPEN_TARGET_DIRECTORY)) && - sizeof(WCHAR) == FileName.Length) - return STATUS_ACCESS_DENIED; - - /* cannot FILE_DELETE_ON_CLOSE on the root directory */ - if (FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE) && - sizeof(WCHAR) == FileName.Length) - return STATUS_CANNOT_DELETE; - Result = FspFileNodeCreate(FsvolDeviceObject, FileName.Length, &FileNode); @@ -297,25 +268,40 @@ static NTSTATUS FspFsvolCreateNoLock( FileNode->FileName.Buffer += FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR); } + ASSERT(sizeof(WCHAR) <= FileNode->FileName.Length && L'\\' == FileNode->FileName.Buffer[0]); + /* check for trailing backslash */ if (sizeof(WCHAR) * 2/* not empty or root */ <= FileNode->FileName.Length && L'\\' == FileNode->FileName.Buffer[FileNode->FileName.Length / sizeof(WCHAR) - 1]) { - FileNode->FileName.Length -= sizeof(WCHAR); - HasTrailingBackslash = TRUE; - - if (sizeof(WCHAR) * 2 <= FileNode->FileName.Length && - L'\\' == FileNode->FileName.Buffer[FileNode->FileName.Length / sizeof(WCHAR) - 1]) + if (!FlagOn(CreateOptions, FILE_DIRECTORY_FILE)) { FspFileNodeDereference(FileNode); return STATUS_OBJECT_NAME_INVALID; } + + FileNode->FileName.Length -= sizeof(WCHAR); } - if (HasTrailingBackslash && !FlagOn(CreateOptions, FILE_DIRECTORY_FILE)) - { + + /* not all operations allowed on the root directory */ + if (sizeof(WCHAR) == FileNode->FileName.Length && + (FILE_CREATE == CreateDisposition || + FILE_OVERWRITE == CreateDisposition || + FILE_OVERWRITE_IF == CreateDisposition || + FILE_SUPERSEDE == CreateDisposition || + BooleanFlagOn(Flags, SL_OPEN_TARGET_DIRECTORY))) + { FspFileNodeDereference(FileNode); - return STATUS_OBJECT_NAME_INVALID; - } + return STATUS_ACCESS_DENIED; + } + + /* cannot FILE_DELETE_ON_CLOSE on the root directory */ + if (sizeof(WCHAR) == FileNode->FileName.Length && + FlagOn(CreateOptions, FILE_DELETE_ON_CLOSE)) + { + FspFileNodeDereference(FileNode); + return STATUS_CANNOT_DELETE; + } Result = FspFileDescCreate(&FileDesc); if (!NT_SUCCESS(Result))