[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.
This commit is contained in:
Timo Kreuzer 2023-04-09 19:10:38 +03:00
parent 54d1b39676
commit 918e331970

View file

@ -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;
}