From fd334021040e0377816e0ca198c9940ed8135e3a Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Thu, 4 Oct 2018 01:16:17 +0200 Subject: [PATCH] [NTOSKRNL] NtReadFile/NtWriteFile: If a file has been opened for non-cached access, Length and ByteOffset must be sector size aligned. This fixed two ntdll apitests. --- ntoskrnl/io/iomgr/iofunc.c | 83 ++++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 16 deletions(-) diff --git a/ntoskrnl/io/iomgr/iofunc.c b/ntoskrnl/io/iomgr/iofunc.c index 58a63167517..c344b422d8a 100644 --- a/ntoskrnl/io/iomgr/iofunc.c +++ b/ntoskrnl/io/iomgr/iofunc.c @@ -2579,6 +2579,18 @@ NtReadFile(IN HANDLE FileHandle, CapturedByteOffset.QuadPart = 0; IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); + /* Get File Object */ + Status = ObReferenceObjectByHandle(FileHandle, + FILE_READ_DATA, + IoFileObjectType, + PreviousMode, + (PVOID*)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) return Status; + + /* Get the device object */ + DeviceObject = IoGetRelatedDeviceObject(FileObject); + /* Validate User-Mode Buffers */ if (PreviousMode != KernelMode) { @@ -2597,12 +2609,38 @@ NtReadFile(IN HANDLE FileHandle, CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset); } + /* Perform additional checks for non-cached file access */ + if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) + { + /* Fail if Length is not sector size aligned */ + if ((DeviceObject->SectorSize != 0) && + (Length % DeviceObject->SectorSize != 0)) + { + /* Release the file object and and fail */ + ObDereferenceObject(FileObject); + return STATUS_INVALID_PARAMETER; + } + + if (ByteOffset) + { + /* Fail if ByteOffset is not sector size aligned */ + if ((DeviceObject->SectorSize != 0) && + (ByteOffset->QuadPart % DeviceObject->SectorSize != 0)) + { + /* Release the file object and and fail */ + ObDereferenceObject(FileObject); + return STATUS_INVALID_PARAMETER; + } + } + } + /* Capture and probe the key */ if (Key) CapturedKey = ProbeForReadUlong(Key); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* Return the exception code */ + /* Release the file object and return the exception code */ + ObDereferenceObject(FileObject); _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; @@ -2614,15 +2652,6 @@ NtReadFile(IN HANDLE FileHandle, if (Key) CapturedKey = *Key; } - /* Get File Object */ - Status = ObReferenceObjectByHandle(FileHandle, - FILE_READ_DATA, - IoFileObjectType, - PreviousMode, - (PVOID*)&FileObject, - NULL); - if (!NT_SUCCESS(Status)) return Status; - /* Check for event */ if (Event) { @@ -2644,9 +2673,6 @@ NtReadFile(IN HANDLE FileHandle, KeClearEvent(EventObject); } - /* Get the device object */ - DeviceObject = IoGetRelatedDeviceObject(FileObject); - /* Check if we should use Sync IO or not */ if (FileObject->Flags & FO_SYNCHRONOUS_IO) { @@ -3591,6 +3617,9 @@ NtWriteFile(IN HANDLE FileHandle, &ObjectHandleInfo); if (!NT_SUCCESS(Status)) return Status; + /* Get the device object */ + DeviceObject = IoGetRelatedDeviceObject(FileObject); + /* Validate User-Mode Buffers */ if (PreviousMode != KernelMode) { @@ -3609,6 +3638,31 @@ NtWriteFile(IN HANDLE FileHandle, CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset); } + /* Perform additional checks for non-cached file access */ + if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) + { + /* Fail if Length is not sector size aligned */ + if ((DeviceObject->SectorSize != 0) && + (Length % DeviceObject->SectorSize != 0)) + { + /* Release the file object and and fail */ + ObDereferenceObject(FileObject); + return STATUS_INVALID_PARAMETER; + } + + if (ByteOffset) + { + /* Fail if ByteOffset is not sector size aligned */ + if ((DeviceObject->SectorSize != 0) && + (ByteOffset->QuadPart % DeviceObject->SectorSize != 0)) + { + /* Release the file object and and fail */ + ObDereferenceObject(FileObject); + return STATUS_INVALID_PARAMETER; + } + } + } + /* Capture and probe the key */ if (Key) CapturedKey = ProbeForReadUlong(Key); } @@ -3657,9 +3711,6 @@ NtWriteFile(IN HANDLE FileHandle, KeClearEvent(EventObject); } - /* Get the device object */ - DeviceObject = IoGetRelatedDeviceObject(FileObject); - /* Check if we should use Sync IO or not */ if (FileObject->Flags & FO_SYNCHRONOUS_IO) {