https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5949d5095d95d1ab5118f24f00193ded2670b825
commit 5949d5095d95d1ab5118f24f00193ded2670b825 Author: Jérôme Gardou <jerome.gar...@reactos.org> AuthorDate: Tue Jan 5 18:39:55 2021 +0100 Commit: Jérôme Gardou <jerome.gar...@reactos.org> CommitDate: Wed Feb 3 09:41:23 2021 +0100 [NTOS:CC][NTOS:MM] Try respecting ValidDataLength --- ntoskrnl/cc/copy.c | 38 ++++++++++++++++++++++++++++++++++++-- ntoskrnl/cc/fs.c | 1 + ntoskrnl/cc/pin.c | 5 +++++ ntoskrnl/cc/view.c | 1 + ntoskrnl/include/internal/cc.h | 1 + ntoskrnl/mm/section.c | 15 ++++++++++++--- 6 files changed, 56 insertions(+), 5 deletions(-) diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c index 677ab00dd2f..8ed24f2bd92 100644 --- a/ntoskrnl/cc/copy.c +++ b/ntoskrnl/cc/copy.c @@ -504,6 +504,24 @@ CcCopyRead ( CurrentOffset = FileOffset->QuadPart; while(CurrentOffset < ReadEnd) { + if (CurrentOffset >= SharedCacheMap->ValidDataLength.QuadPart) + { + DPRINT1("Zeroing buffer because we are beyond the VDL.\n"); + /* We are beyond what is valid. Just zero this out */ + _SEH2_TRY + { + RtlZeroMemory(Buffer, Length); + } + _SEH2_EXCEPT(CcpCheckInvalidUserBuffer(_SEH2_GetExceptionInformation(), Buffer, Length)) + { + ExRaiseStatus(STATUS_INVALID_USER_BUFFER); + } + _SEH2_END; + + ReadLength += Length; + break; + } + Status = CcRosGetVacb(SharedCacheMap, CurrentOffset, &Vacb); if (!NT_SUCCESS(Status)) { @@ -598,7 +616,7 @@ CcCopyWrite ( PROS_SHARED_CACHE_MAP SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; NTSTATUS Status; LONGLONG CurrentOffset; - LONGLONG WriteEnd = FileOffset->QuadPart + Length; + LONGLONG WriteEnd; CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%I64d Length=%lu Wait=%d Buffer=%p\n", FileObject, FileOffset->QuadPart, Length, Wait, Buffer); @@ -610,7 +628,11 @@ CcCopyWrite ( if (!SharedCacheMap) return FALSE; - ASSERT((FileOffset->QuadPart + Length) <= SharedCacheMap->SectionSize.QuadPart); + Status = RtlLongLongAdd(FileOffset->QuadPart, Length, &WriteEnd); + if (!NT_SUCCESS(Status)) + ExRaiseStatus(Status); + + ASSERT(WriteEnd <= SharedCacheMap->SectionSize.QuadPart); CurrentOffset = FileOffset->QuadPart; while(CurrentOffset < WriteEnd) @@ -662,6 +684,10 @@ CcCopyWrite ( if (FileObject->Flags & FO_WRITE_THROUGH) CcFlushCache(FileObject->SectionObjectPointer, FileOffset, Length, NULL); + /* Update VDL */ + if (WriteEnd > SharedCacheMap->ValidDataLength.QuadPart) + SharedCacheMap->ValidDataLength.QuadPart = WriteEnd; + return TRUE; } @@ -871,6 +897,14 @@ CcZeroData ( return TRUE; } + /* See if we should simply truncate the valid data length */ + if ((StartOffset->QuadPart < SharedCacheMap->ValidDataLength.QuadPart) && (EndOffset->QuadPart > SharedCacheMap->ValidDataLength.QuadPart)) + { + DPRINT1("Truncating VDL.\n"); + SharedCacheMap->ValidDataLength = *StartOffset; + return TRUE; + } + ASSERT(EndOffset->QuadPart <= SharedCacheMap->SectionSize.QuadPart); while(WriteOffset.QuadPart < EndOffset->QuadPart) diff --git a/ntoskrnl/cc/fs.c b/ntoskrnl/cc/fs.c index 7a4c8cf4df2..161833d14e2 100644 --- a/ntoskrnl/cc/fs.c +++ b/ntoskrnl/cc/fs.c @@ -297,6 +297,7 @@ CcSetFileSizes ( OldSectionSize = SharedCacheMap->SectionSize; SharedCacheMap->SectionSize = FileSizes->AllocationSize; SharedCacheMap->FileSize = FileSizes->FileSize; + SharedCacheMap->ValidDataLength = FileSizes->ValidDataLength; KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql); if (FileSizes->AllocationSize.QuadPart < OldSectionSize.QuadPart) diff --git a/ntoskrnl/cc/pin.c b/ntoskrnl/cc/pin.c index ae62d2da0bc..07bfd63241c 100644 --- a/ntoskrnl/cc/pin.c +++ b/ntoskrnl/cc/pin.c @@ -543,6 +543,7 @@ CcSetDirtyPinnedData ( IN PLARGE_INTEGER Lsn) { PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB); + PROS_SHARED_CACHE_MAP SharedCacheMap = iBcb->Vacb->SharedCacheMap; CCTRACE(CC_API_DEBUG, "Bcb=%p Lsn=%p\n", Bcb, Lsn); @@ -555,6 +556,10 @@ CcSetDirtyPinnedData ( { CcRosMarkDirtyVacb(iBcb->Vacb); } + + /* Update VDL */ + if (SharedCacheMap->ValidDataLength.QuadPart < (iBcb->PFCB.MappedFileOffset.QuadPart + iBcb->PFCB.MappedLength)) + SharedCacheMap->ValidDataLength.QuadPart = iBcb->PFCB.MappedFileOffset.QuadPart + iBcb->PFCB.MappedLength; } diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c index 21fd37ad681..06ec86788a9 100644 --- a/ntoskrnl/cc/view.c +++ b/ntoskrnl/cc/view.c @@ -1182,6 +1182,7 @@ CcRosInitializeFileCache ( SharedCacheMap->LazyWriteContext = LazyWriterContext; SharedCacheMap->SectionSize = FileSizes->AllocationSize; SharedCacheMap->FileSize = FileSizes->FileSize; + SharedCacheMap->ValidDataLength = FileSizes->ValidDataLength; SharedCacheMap->PinAccess = PinAccess; SharedCacheMap->DirtyPageThreshold = 0; SharedCacheMap->DirtyPages = 0; diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h index 6416b2e7d3d..7384d9be0d3 100644 --- a/ntoskrnl/include/internal/cc.h +++ b/ntoskrnl/include/internal/cc.h @@ -175,6 +175,7 @@ typedef struct _ROS_SHARED_CACHE_MAP LARGE_INTEGER FileSize; LIST_ENTRY BcbList; LARGE_INTEGER SectionSize; + LARGE_INTEGER ValidDataLength; PFILE_OBJECT FileObject; ULONG DirtyPages; LIST_ENTRY SharedCacheMapLinks; diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index b30462094c7..7ff5485ae81 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -1167,11 +1167,13 @@ MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress) } #ifndef NEWCC +static NTSTATUS NTAPI MiReadPage(PMEMORY_AREA MemoryArea, LONGLONG SegOffset, - PPFN_NUMBER Page) + PPFN_NUMBER Page, + BOOLEAN IgnoreSize) /* * FUNCTION: Read a page for a section backed memory area. * PARAMETERS: @@ -1188,6 +1190,7 @@ MiReadPage(PMEMORY_AREA MemoryArea, PFILE_OBJECT FileObject = MemoryArea->SectionData.Segment->FileObject; LARGE_INTEGER FileOffset; KIRQL OldIrql; + PFSRTL_ADVANCED_FCB_HEADER FcbHeader = FileObject->FsContext; FileOffset.QuadPart = MemoryArea->SectionData.Segment->Image.FileOffset + SegOffset; @@ -1197,6 +1200,12 @@ MiReadPage(PMEMORY_AREA MemoryArea, if (!NT_SUCCESS(Status)) return Status; + if ((FileOffset.QuadPart > FcbHeader->ValidDataLength.QuadPart) && !IgnoreSize) + { + /* Quick path : data is not valid; return a zero-page */ + return STATUS_SUCCESS; + } + RtlZeroMemory(MdlBase, sizeof(MdlBase)); MmInitializeMdl(Mdl, NULL, PAGE_SIZE); MmBuildMdlFromPages(Mdl, Page); @@ -1616,7 +1625,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, else { DPRINT("Getting fresh page for file %wZ at offset %I64d.\n", &Segment->FileObject->FileName, Offset.QuadPart); - Status = MiReadPage(MemoryArea, Offset.QuadPart, &Page); + Status = MiReadPage(MemoryArea, Offset.QuadPart, &Page, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("MiReadPage failed (Status %x)\n", Status); @@ -4592,7 +4601,7 @@ MmMakePagesResident( /* FIXME: Read the whole range at once instead of one page at a time */ /* Ignore file size, as Cc already checked on its side. */ - Status = MiReadPage(MemoryArea, SegmentOffset.QuadPart, &Page); + Status = MiReadPage(MemoryArea, SegmentOffset.QuadPart, &Page, TRUE); if (!NT_SUCCESS(Status)) { /* Reset the Segment entry and fail */