mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:42:57 +00:00
- 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
This commit is contained in:
parent
0342a00bde
commit
ef41fc2623
1 changed files with 72 additions and 36 deletions
|
@ -463,61 +463,97 @@ IopSecurityFile(IN PVOID ObjectBody,
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
NTAPI
|
||||||
IopQueryNameFile(PVOID ObjectBody,
|
IopQueryNameFile(IN PVOID ObjectBody,
|
||||||
IN BOOLEAN HasName,
|
IN BOOLEAN HasName,
|
||||||
POBJECT_NAME_INFORMATION ObjectNameInfo,
|
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||||||
ULONG Length,
|
IN ULONG Length,
|
||||||
PULONG ReturnLength,
|
OUT PULONG ReturnLength,
|
||||||
IN KPROCESSOR_MODE PreviousMode)
|
IN KPROCESSOR_MODE PreviousMode)
|
||||||
{
|
{
|
||||||
POBJECT_NAME_INFORMATION LocalInfo;
|
POBJECT_NAME_INFORMATION LocalInfo;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_NAME_INFORMATION LocalFileInfo;
|
||||||
ULONG LocalReturnLength;
|
PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
|
||||||
|
ULONG LocalReturnLength, FileLength;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PWCHAR p;
|
||||||
|
|
||||||
DPRINT1("IopQueryNameFile() called\n");
|
/* Validate length */
|
||||||
|
if (Length < sizeof(OBJECT_NAME_INFORMATION))
|
||||||
FileObject = (PFILE_OBJECT)ObjectBody;
|
{
|
||||||
|
/* Wrong length, fail */
|
||||||
|
return STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate Buffer */
|
/* Allocate Buffer */
|
||||||
LocalInfo = ExAllocatePool(PagedPool,
|
LocalInfo = ExAllocatePoolWithTag(PagedPool, Length, TAG_IO);
|
||||||
sizeof(OBJECT_NAME_INFORMATION) +
|
if (!LocalInfo) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
MAX_PATH * sizeof(WCHAR));
|
|
||||||
if (LocalInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
|
|
||||||
/* Query the name */
|
/* Query the name */
|
||||||
Status = ObQueryNameString(FileObject->DeviceObject,
|
Status = ObQueryNameString(FileObject->DeviceObject,
|
||||||
LocalInfo,
|
LocalInfo,
|
||||||
MAX_PATH * sizeof(WCHAR),
|
Length,
|
||||||
&LocalReturnLength);
|
&LocalReturnLength);
|
||||||
if (!NT_SUCCESS (Status))
|
if (!NT_SUCCESS (Status))
|
||||||
{
|
{
|
||||||
|
/* Free the buffer and fail */
|
||||||
ExFreePool(LocalInfo);
|
ExFreePool(LocalInfo);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
DPRINT ("Device path: %wZ\n", &LocalInfo->Name);
|
|
||||||
|
|
||||||
/* Write Device Path */
|
/* Copy the information */
|
||||||
Status = RtlAppendUnicodeStringToString(&ObjectNameInfo->Name,
|
RtlCopyMemory(ObjectNameInfo,
|
||||||
&(LocalInfo)->Name);
|
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 */
|
/* Query the File name */
|
||||||
Status = IoQueryFileInformation(FileObject,
|
Status = IoQueryFileInformation(FileObject,
|
||||||
FileNameInformation,
|
FileNameInformation,
|
||||||
LocalReturnLength,
|
Length,
|
||||||
LocalInfo,
|
LocalFileInfo,
|
||||||
NULL);
|
&LocalReturnLength);
|
||||||
if (Status != STATUS_SUCCESS)
|
if (NT_ERROR(Status))
|
||||||
{
|
{
|
||||||
|
/* Fail on errors only, allow warnings */
|
||||||
ExFreePool(LocalInfo);
|
ExFreePool(LocalInfo);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the Name */
|
/* Now calculate the new lenghts left */
|
||||||
Status = RtlAppendUnicodeToString(&ObjectNameInfo->Name,
|
FileLength = LocalReturnLength -
|
||||||
((PFILE_NAME_INFORMATION)LocalInfo)->FileName);
|
FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
|
||||||
DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
|
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 */
|
/* Free buffer and return */
|
||||||
ExFreePool(LocalInfo);
|
ExFreePool(LocalInfo);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue