https://git.reactos.org/?p=reactos.git;a=commitdiff;h=918e33197024163fd6e27…
commit 918e33197024163fd6e2781eeed3bb6b7be82270
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Sun Apr 9 19:10:38 2023 +0300
Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org>
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;
}