https://git.reactos.org/?p=reactos.git;a=commitdiff;h=774a4c703fdf241333906…
commit 774a4c703fdf2413339064422f39ef2dbfd88fcc
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Tue Nov 24 14:07:06 2020 +0100
Commit: Jérôme Gardou <jerome.gardou(a)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))