https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8ed15a49a7540a91afc07d8eafe26a952b6d0ae6

commit 8ed15a49a7540a91afc07d8eafe26a952b6d0ae6
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Wed Dec 30 09:43:55 2020 +0100
Commit:     Jérôme Gardou <[email protected]>
CommitDate: Wed Feb 3 09:41:23 2021 +0100

    [NTOS:MM] Fix a race
---
 ntoskrnl/mm/freelist.c |  7 ++++++-
 ntoskrnl/mm/rmap.c     | 27 ++++++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/ntoskrnl/mm/freelist.c b/ntoskrnl/mm/freelist.c
index 93d9bbd9f59..ba16362f546 100644
--- a/ntoskrnl/mm/freelist.c
+++ b/ntoskrnl/mm/freelist.c
@@ -436,7 +436,12 @@ MmGetRmapListHeadPage(PFN_NUMBER Pfn)
     /* Get the entry */
     Pfn1 = MiGetPfnEntry(Pfn);
     ASSERT(Pfn1);
-    ASSERT_IS_ROS_PFN(Pfn1);
+
+    if (!MI_IS_ROS_PFN(Pfn1))
+    {
+        MiReleasePfnLock(oldIrql);
+        return NULL;
+    }
 
     /* Get the list head */
     ListHead = Pfn1->RmapListHead;
diff --git a/ntoskrnl/mm/rmap.c b/ntoskrnl/mm/rmap.c
index c000953cca1..785539ea58d 100644
--- a/ntoskrnl/mm/rmap.c
+++ b/ntoskrnl/mm/rmap.c
@@ -149,7 +149,32 @@ MmPageOutPhysicalAddress(PFN_NUMBER Page)
 
         /* Delete this virtual mapping in the process */
         MmDeleteVirtualMapping(Process, Address, &Dirty, &MapPage);
-        ASSERT(MapPage == Page);
+
+        /* There is a window betwwen the start of this function and now,
+         * where it's possible that the process changed its memory layout,
+         * because of copy-on-write, unmapping memory, or whatsoever.
+         * Just go away if that is the case */
+        if (MapPage != Page)
+        {
+            PMM_REGION Region = 
MmFindRegion((PVOID)MA_GetStartingAddress(MemoryArea),
+                            &MemoryArea->SectionData.RegionListHead,
+                            Address, NULL);
+            /* Restore the mapping */
+            MmCreateVirtualMapping(Process, Address, Region->Protect, 
&MapPage, 1);
+            if (Dirty)
+                MmSetDirtyPage(Process, Address);
+
+            MmUnlockSectionSegment(Segment);
+            MmUnlockAddressSpace(AddressSpace);
+            if (Address < MmSystemRangeStart)
+            {
+                ExReleaseRundownProtection(&Process->RundownProtect);
+                ObDereferenceObject(Process);
+            }
+
+            /* We can still try to flush it to disk, though */
+            goto WriteSegment;
+        }
 
         if (Page != PFN_FROM_SSE(Entry))
         {

Reply via email to