https://git.reactos.org/?p=reactos.git;a=commitdiff;h=918e33197024163fd6e2781eeed3bb6b7be82270

commit 918e33197024163fd6e2781eeed3bb6b7be82270
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Sun Apr 9 19:10:38 2023 +0300
Commit:     Timo Kreuzer <[email protected]>
CommitDate: Sat Jul 29 14:00:44 2023 +0300

    [NTOS:Mm] Fix race condition in _MmSetPageEntrySectionSegment
    
    The function updates the entry in the section page table and updates the 
section association rmaps for it. In the page-in path, when the new section 
association is set before the entry is updated, a concurrent attempt to unmap 
the page would find an inconsistent entry, where there is an rmap, but the 
section page table entry is still an MM_WAIT_ENTRY.
---
 ntoskrnl/cache/section/sptab.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/ntoskrnl/cache/section/sptab.c b/ntoskrnl/cache/section/sptab.c
index 5149ea3b76e..83f7c5f542a 100644
--- a/ntoskrnl/cache/section/sptab.c
+++ b/ntoskrnl/cache/section/sptab.c
@@ -223,8 +223,17 @@ _MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
             if (PFN_FROM_SSE(Entry) != PFN_FROM_SSE(OldEntry))
             {
                 MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
+
+                /* This has to be done before setting the new section 
association
+                   to prevent a race condition with the paging out path */
+                PageTable->PageEntries[PageIndex] = Entry;
+
                 MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset);
             }
+            else
+            {
+                PageTable->PageEntries[PageIndex] = Entry;
+            }
         }
         else
         {
@@ -232,6 +241,7 @@ _MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
              * We're switching to a valid entry from an invalid one.
              * Add the Rmap and take a ref on the segment.
              */
+            PageTable->PageEntries[PageIndex] = Entry;
             MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset);
 
             if (Offset->QuadPart >= (Segment->LastPage << PAGE_SHIFT))
@@ -242,6 +252,7 @@ _MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
     {
         /* We're switching to an invalid entry from a valid one */
         MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
+        PageTable->PageEntries[PageIndex] = Entry;
 
         if (Offset->QuadPart == ((Segment->LastPage - 1ULL) << PAGE_SHIFT))
         {
@@ -256,8 +267,11 @@ _MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
             }
         }
     }
+    else
+    {
+        PageTable->PageEntries[PageIndex] = Entry;
+    }
 
-    PageTable->PageEntries[PageIndex] = Entry;
     return STATUS_SUCCESS;
 }
 

Reply via email to