https://git.reactos.org/?p=reactos.git;a=commitdiff;h=774a4c703fdf2413339064422f39ef2dbfd88fcc

commit 774a4c703fdf2413339064422f39ef2dbfd88fcc
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Tue Nov 24 14:07:06 2020 +0100
Commit:     Jérôme Gardou <[email protected]>
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))

Reply via email to