sys: FspFsvolReadNonCached: trim ReadLength

During CreateProcess/CreateSection Windows locks the image file (using AcquireFileForNtCreateSection),
gets the image file size and then reads the image file. Unfortunately if the file system (erroneously) reads
past the file size, Windows can bugcheck. This allows a faulty or malicious file system to crash Windows.

This commit adds a check in WinFsp to mitigate this problem.
This commit is contained in:
Bill Zissimopoulos 2020-04-10 19:24:43 -07:00
parent 9d69ae7503
commit 42fd57904a
No known key found for this signature in database
GPG Key ID: 3D4F95D52C7B3EA3
3 changed files with 20 additions and 0 deletions

View File

@ -78,6 +78,7 @@ VOID FspAcquireFileForNtCreateSection(
{
/* Callers:
* CcWriteBehind
* MmCreateSection and friends
*/
FSP_ENTER_VOID(PAGED_CODE());
@ -85,6 +86,8 @@ VOID FspAcquireFileForNtCreateSection(
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FspFileNodeAcquireExclusive(FileNode, Full);
ASSERT(FALSE == FileNode->Tls.CreateSection);
FileNode->Tls.CreateSection = TRUE;
FSP_LEAVE_VOID("FileObject=%p", FileObject);
}
@ -94,12 +97,14 @@ VOID FspReleaseFileForNtCreateSection(
{
/* Callers:
* CcWriteBehind
* MmCreateSection and friends
*/
FSP_ENTER_VOID(PAGED_CODE());
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FileNode->Tls.CreateSection = FALSE;
FspFileNodeRelease(FileNode, Full);
FSP_LEAVE_VOID("FileObject=%p", FileObject);

View File

@ -1392,6 +1392,7 @@ typedef struct FSP_FILE_NODE
PIRP TopLevelIrp;
UINT32 TopFlags;
} CcFlush;
BOOLEAN CreateSection;
} Tls;
/* read-only after creation (and insertion in the ContextTable) */
PDEVICE_OBJECT FsvolDeviceObject;

View File

@ -234,6 +234,7 @@ static NTSTATUS FspFsvolReadNonCached(
ULONG ReadLength = IrpSp->Parameters.Read.Length;
ULONG ReadKey = IrpSp->Parameters.Read.Key;
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
FSP_FSCTL_FILE_INFO FileInfo;
FSP_FSCTL_TRANSACT_REQ *Request;
BOOLEAN Success;
@ -296,6 +297,19 @@ static NTSTATUS FspFsvolReadNonCached(
}
}
/* trim ReadLength during CreateProcess; resolve bugcheck for filesystem that reports incorrect size */
if (FileNode->Tls.CreateSection)
{
FspFileNodeGetFileInfo(FileNode, &FileInfo);
if ((UINT64)ReadOffset.QuadPart >= FileInfo.FileSize)
{
FspFileNodeRelease(FileNode, Full);
return STATUS_END_OF_FILE;
}
if ((UINT64)ReadLength > FileInfo.FileSize - ReadOffset.QuadPart)
ReadLength = (ULONG)(FileInfo.FileSize - ReadOffset.QuadPart);
}
/* convert FileNode to shared */
FspFileNodeConvertExclusiveToShared(FileNode, Full);