[NTOS:CC][NTOS:MM] Try respecting ValidDataLength

This commit is contained in:
Jérôme Gardou 2021-01-05 18:39:55 +01:00
parent bdb73edab7
commit 5949d5095d
6 changed files with 56 additions and 5 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

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