https://git.reactos.org/?p=reactos.git;a=commitdiff;h=774a4c703fdf2413339064...
commit 774a4c703fdf2413339064422f39ef2dbfd88fcc Author: Jérôme Gardou jerome.gardou@reactos.org AuthorDate: Tue Nov 24 14:07:06 2020 +0100 Commit: Jérôme Gardou jerome.gardou@reactos.org CommitDate: Wed Feb 3 09:41:22 2021 +0100
[NTOS/MM] Misc fixes
Purge data section object before creating an image mapping Zero-out the tail of the page after reading from file Properly map page as read-only when paging-in a COW memory map. --- ntoskrnl/mm/section.c | 92 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 24 deletions(-)
diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index f108533ed2e..8df9b99cfb8 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -1214,6 +1214,18 @@ MiReadPage(PMEMORY_AREA MemoryArea, Status = STATUS_SUCCESS; }
+ if ((SegOffset + PAGE_SIZE) > MemoryArea->SectionData.Segment->RawLength.QuadPart) + { + KIRQL OldIrql; + PUCHAR PageMap; + + /* Zero out the end of it */ + PageMap = MiMapPageInHyperSpace(PsGetCurrentProcess(), *Page, &OldIrql); + RtlZeroMemory(PageMap + MemoryArea->SectionData.Segment->RawLength.QuadPart - SegOffset, + PAGE_SIZE - (MemoryArea->SectionData.Segment->RawLength.QuadPart - SegOffset)); + MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PageMap, OldIrql); + } + return Status; }
@@ -1448,32 +1460,24 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, { SWAPENTRY DummyEntry;
- /* - * Is it a wait entry? - */ - if (HasSwapEntry) + MmGetPageFileMapping(Process, Address, &SwapEntry); + if (SwapEntry == MM_WAIT_ENTRY) { - MmGetPageFileMapping(Process, Address, &SwapEntry); - - if (SwapEntry == MM_WAIT_ENTRY) - { - MmUnlockSectionSegment(Segment); - MmUnlockAddressSpace(AddressSpace); - MiWaitForPageEvent(NULL, NULL); - MmLockAddressSpace(AddressSpace); - return STATUS_MM_RESTART_OPERATION; - } - - /* - * Must be private page we have swapped out. - */ - - /* - * Sanity check - */ - MmDeletePageFileMapping(Process, Address, &SwapEntry); + MmUnlockSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); + MiWaitForPageEvent(NULL, NULL); + MmLockAddressSpace(AddressSpace); + return STATUS_MM_RESTART_OPERATION; }
+ /* + * Must be private page we have swapped out. + */ + + /* + * Sanity check + */ + MmDeletePageFileMapping(Process, Address, &SwapEntry); MmUnlockSectionSegment(Segment);
/* Tell everyone else we are serving the fault. */ @@ -1709,7 +1713,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, /* Map the page into the process address space */ Status = MmCreateVirtualMapping(Process, PAddress, - Region->Protect, + Attributes, &Page, 1); if (!NT_SUCCESS(Status)) @@ -3096,6 +3100,7 @@ MmCreateImageSection(PSECTION *SectionObject, if (ImageSectionObject == NULL) { NTSTATUS StatusExeFmt; + PMM_SECTION_SEGMENT DataSectionObject;
ImageSectionObject = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT); if (ImageSectionObject == NULL) @@ -3112,8 +3117,47 @@ MmCreateImageSection(PSECTION *SectionObject, ImageSectionObject->RefCount = 1; FileObject->SectionObjectPointer->ImageSectionObject = ImageSectionObject;
+ /* Get a ref on the data section object */ + DataSectionObject = FileObject->SectionObjectPointer->DataSectionObject; + while (DataSectionObject && (DataSectionObject->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE))) + { + LARGE_INTEGER ShortTime; + + MiReleasePfnLock(OldIrql); + + ShortTime.QuadPart = - 10 * 100 * 1000; + KeDelayExecutionThread(KernelMode, FALSE, &ShortTime); + + OldIrql = MiAcquirePfnLock(); + DataSectionObject = FileObject->SectionObjectPointer->DataSectionObject; + ASSERT(DataSectionObject->SegFlags & MM_DATAFILE_SEGMENT); + } + + /* Get a ref on it. */ + if (DataSectionObject) + InterlockedIncrementUL(&DataSectionObject->RefCount); + MiReleasePfnLock(OldIrql);
+ if (DataSectionObject) + { + if ((DataSectionObject->SectionCount - (FileObject->SectionObjectPointer->SharedCacheMap != NULL)) > 0) + { + /* Someone's got a section opened. Deny creation */ + DPRINT1("Denying image creation for %wZ: Sections opened: %lu.\n", + &FileObject->FileName, DataSectionObject->SectionCount); + InterlockedExchangePointer(&FileObject->SectionObjectPointer->ImageSectionObject, NULL); + ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT); + MmDereferenceSegment(DataSectionObject); + ObDereferenceObject(FileObject); + ObDereferenceObject(Section); + return STATUS_ACCESS_DENIED; + } + + /* Purge the cache. */ + CcPurgeCacheSection(FileObject->SectionObjectPointer, NULL, 0, FALSE); + } + StatusExeFmt = ExeFmtpCreateImageSection(FileObject, ImageSectionObject);
if (!NT_SUCCESS(StatusExeFmt))