From 42fd57904a97ad10ec245e740e63973ec0982c96 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Fri, 10 Apr 2020 19:24:43 -0700 Subject: [PATCH] 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. --- src/sys/callbacks.c | 5 +++++ src/sys/driver.h | 1 + src/sys/read.c | 14 ++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/src/sys/callbacks.c b/src/sys/callbacks.c index 15551d8b..af3d94e8 100644 --- a/src/sys/callbacks.c +++ b/src/sys/callbacks.c @@ -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); diff --git a/src/sys/driver.h b/src/sys/driver.h index 1a78518d..f87f1bb9 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -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; diff --git a/src/sys/read.c b/src/sys/read.c index c2581309..748e9185 100644 --- a/src/sys/read.c +++ b/src/sys/read.c @@ -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);