From ef41fc2623bac2c762a2399b147d4d7615beb9f5 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Tue, 4 Jul 2006 23:31:42 +0000 Subject: [PATCH] - Fix IopQueryNameFile to properly validate and calculate lengths at each step of the way and to support incomplete buffers. Previously, dangerous assumptions were made about the buffers and the actual required length was never returned. svn path=/trunk/; revision=22853 --- reactos/ntoskrnl/io/iomgr/file.c | 108 ++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 36 deletions(-) diff --git a/reactos/ntoskrnl/io/iomgr/file.c b/reactos/ntoskrnl/io/iomgr/file.c index ab7e13ddf33..6965e54a10f 100644 --- a/reactos/ntoskrnl/io/iomgr/file.c +++ b/reactos/ntoskrnl/io/iomgr/file.c @@ -463,61 +463,97 @@ IopSecurityFile(IN PVOID ObjectBody, } NTSTATUS -STDCALL -IopQueryNameFile(PVOID ObjectBody, +NTAPI +IopQueryNameFile(IN PVOID ObjectBody, IN BOOLEAN HasName, - POBJECT_NAME_INFORMATION ObjectNameInfo, - ULONG Length, - PULONG ReturnLength, + OUT POBJECT_NAME_INFORMATION ObjectNameInfo, + IN ULONG Length, + OUT PULONG ReturnLength, IN KPROCESSOR_MODE PreviousMode) { POBJECT_NAME_INFORMATION LocalInfo; - PFILE_OBJECT FileObject; - ULONG LocalReturnLength; + PFILE_NAME_INFORMATION LocalFileInfo; + PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody; + ULONG LocalReturnLength, FileLength; NTSTATUS Status; + PWCHAR p; - DPRINT1("IopQueryNameFile() called\n"); - - FileObject = (PFILE_OBJECT)ObjectBody; + /* Validate length */ + if (Length < sizeof(OBJECT_NAME_INFORMATION)) + { + /* Wrong length, fail */ + return STATUS_INFO_LENGTH_MISMATCH; + } /* Allocate Buffer */ - LocalInfo = ExAllocatePool(PagedPool, - sizeof(OBJECT_NAME_INFORMATION) + - MAX_PATH * sizeof(WCHAR)); - if (LocalInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES; + LocalInfo = ExAllocatePoolWithTag(PagedPool, Length, TAG_IO); + if (!LocalInfo) return STATUS_INSUFFICIENT_RESOURCES; /* Query the name */ Status = ObQueryNameString(FileObject->DeviceObject, LocalInfo, - MAX_PATH * sizeof(WCHAR), + Length, &LocalReturnLength); if (!NT_SUCCESS (Status)) { - ExFreePool (LocalInfo); - return Status; - } - DPRINT ("Device path: %wZ\n", &LocalInfo->Name); - - /* Write Device Path */ - Status = RtlAppendUnicodeStringToString(&ObjectNameInfo->Name, - &(LocalInfo)->Name); - - /* Query the File name */ - Status = IoQueryFileInformation(FileObject, - FileNameInformation, - LocalReturnLength, - LocalInfo, - NULL); - if (Status != STATUS_SUCCESS) - { + /* Free the buffer and fail */ ExFreePool(LocalInfo); return Status; } - /* Write the Name */ - Status = RtlAppendUnicodeToString(&ObjectNameInfo->Name, - ((PFILE_NAME_INFORMATION)LocalInfo)->FileName); - DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name); + /* Copy the information */ + RtlCopyMemory(ObjectNameInfo, + LocalInfo, + LocalReturnLength > Length ? + Length : LocalReturnLength); + + /* Set buffer pointer */ + p = (PWCHAR)(ObjectNameInfo + 1); + ObjectNameInfo->Name.Buffer = p; + + /* Advance in buffer */ + p += (LocalInfo->Name.Length / sizeof(WCHAR)); + + /* Now get the file name buffer and check the length needed */ + LocalFileInfo = (PFILE_NAME_INFORMATION)LocalInfo; + FileLength = Length - + LocalReturnLength + + FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); + + /* Query the File name */ + Status = IoQueryFileInformation(FileObject, + FileNameInformation, + Length, + LocalFileInfo, + &LocalReturnLength); + if (NT_ERROR(Status)) + { + /* Fail on errors only, allow warnings */ + ExFreePool(LocalInfo); + return Status; + } + + /* Now calculate the new lenghts left */ + FileLength = LocalReturnLength - + FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); + LocalReturnLength = (ULONG_PTR)p - + (ULONG_PTR)ObjectNameInfo + + LocalFileInfo->FileNameLength; + + /* Write the Name and null-terminate it */ + RtlMoveMemory(p, LocalFileInfo->FileName, FileLength); + p += (FileLength / sizeof(WCHAR)); + *p = UNICODE_NULL; + LocalReturnLength += sizeof(UNICODE_NULL); + + /* Return the length needed */ + *ReturnLength = LocalReturnLength; + + /* Setup the length and maximum length */ + FileLength = (ULONG_PTR)p - (ULONG_PTR)ObjectNameInfo; + ObjectNameInfo->Name.Length = Length - sizeof(OBJECT_NAME_INFORMATION); + ObjectNameInfo->Name.MaximumLength = ObjectNameInfo->Name.Length + + sizeof(UNICODE_NULL); /* Free buffer and return */ ExFreePool(LocalInfo);