https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5949d5095d95d1ab5118f…
commit 5949d5095d95d1ab5118f24f00193ded2670b825
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Tue Jan 5 18:39:55 2021 +0100
Commit: Jérôme Gardou <jerome.gardou(a)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 */