sys: rename: bail early when attempting to replace directory

This commit is contained in:
Bill Zissimopoulos 2016-11-22 15:47:34 -08:00
parent ba78fbb956
commit 1f385a9ab5
2 changed files with 22 additions and 4 deletions

View File

@ -1067,7 +1067,7 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
if (!CheckingOldName) if (!CheckingOldName)
{ {
/* make sure no processes are mapping any descendants as an image */ /* replaced file cannot be a directory or mapped as an image */
for ( for (
DescendantFileNodeIndex = 0; DescendantFileNodeIndex = 0;
DescendantFileNodeCount > DescendantFileNodeIndex; DescendantFileNodeCount > DescendantFileNodeIndex;
@ -1076,7 +1076,9 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex]; DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~7); DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~7);
if (!MmFlushImageSection(&DescendantFileNode->NonPaged->SectionObjectPointers, if ((DescendantFileNode->FileName.Length > FileName->Length &&
L'\\' == DescendantFileNode->FileName.Buffer[FileName->Length / sizeof(WCHAR)]) ||
!MmFlushImageSection(&DescendantFileNode->NonPaged->SectionObjectPointers,
MmFlushForDelete)) MmFlushForDelete))
{ {
/* release the FileNode in case of failure! */ /* release the FileNode in case of failure! */

View File

@ -537,7 +537,7 @@ static void rename_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
Success = MoveFileExW(File1Path, File2Path, 0); Success = MoveFileExW(File1Path, File2Path, 0);
ASSERT(Success); ASSERT(Success);
/* cannot replace existing directory regardless of MOVEFILE_REPLACE_EXISTING */ /* cannot replace existing directory regardless of MOVEFILE_REPLACE_EXISTING -- test MEMFS */
Success = MoveFileExW(Dir2Path, Dir1Path, MOVEFILE_REPLACE_EXISTING); Success = MoveFileExW(Dir2Path, Dir1Path, MOVEFILE_REPLACE_EXISTING);
ASSERT(!Success); ASSERT(!Success);
ASSERT(ERROR_ACCESS_DENIED == GetLastError()); ASSERT(ERROR_ACCESS_DENIED == GetLastError());
@ -562,6 +562,22 @@ static void rename_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
CloseHandle(Handle); CloseHandle(Handle);
Success = CreateDirectoryW(Dir1Path, 0);
ASSERT(Success);
/* cannot replace existing directory regardless of MOVEFILE_REPLACE_EXISTING -- test FSD */
Handle = CreateFileW(File2Path,
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
OPEN_EXISTING, 0, 0);
ASSERT(INVALID_HANDLE_VALUE != Handle);
Success = MoveFileExW(Dir1Path, Dir2Path, MOVEFILE_REPLACE_EXISTING);
ASSERT(!Success);
ASSERT(ERROR_ACCESS_DENIED == GetLastError());
CloseHandle(Handle);
Success = RemoveDirectoryW(Dir1Path);
ASSERT(Success);
Success = DeleteFileW(File2Path); Success = DeleteFileW(File2Path);
ASSERT(Success); ASSERT(Success);