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