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 */

Reply via email to