[NTOS:Mm] Fix locking for MmGetSectionAssociation

MmGetSectionAssociation races with _MmSetPageEntrySectionSegment without sharing a lock. So we need to hold the PFN lock, until we have referenced the section segment found in the RMAP. This prevents that a section segment, which still has associated RMAPs from being deleted behind our back.
This commit is contained in:
Timo Kreuzer 2023-04-10 00:26:34 +03:00
parent 477792856e
commit 54d1b39676
2 changed files with 9 additions and 4 deletions

View file

@ -364,6 +364,8 @@ MmGetSectionAssociation(PFN_NUMBER Page,
PMM_SECTION_SEGMENT Segment = NULL; PMM_SECTION_SEGMENT Segment = NULL;
PCACHE_SECTION_PAGE_TABLE PageTable; PCACHE_SECTION_PAGE_TABLE PageTable;
KIRQL OldIrql = MiAcquirePfnLock();
PageTable = MmGetSegmentRmap(Page, &RawOffset); PageTable = MmGetSegmentRmap(Page, &RawOffset);
if (PageTable) if (PageTable)
{ {
@ -374,6 +376,8 @@ MmGetSectionAssociation(PFN_NUMBER Page,
InterlockedIncrement64(Segment->ReferenceCount); InterlockedIncrement64(Segment->ReferenceCount);
} }
MiReleasePfnLock(OldIrql);
return Segment; return Segment;
} }

View file

@ -469,7 +469,9 @@ MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset)
{ {
PCACHE_SECTION_PAGE_TABLE Result = NULL; PCACHE_SECTION_PAGE_TABLE Result = NULL;
PMM_RMAP_ENTRY current_entry;//, previous_entry; PMM_RMAP_ENTRY current_entry;//, previous_entry;
KIRQL OldIrql = MiAcquirePfnLock();
/* Must hold the PFN lock */
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
//previous_entry = NULL; //previous_entry = NULL;
current_entry = MmGetRmapListHeadPage(Page); current_entry = MmGetRmapListHeadPage(Page);
@ -481,16 +483,15 @@ MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset)
*RawOffset = (ULONG_PTR)current_entry->Address & ~RMAP_SEGMENT_MASK; *RawOffset = (ULONG_PTR)current_entry->Address & ~RMAP_SEGMENT_MASK;
if (*Result->Segment->Flags & MM_SEGMENT_INDELETE) if (*Result->Segment->Flags & MM_SEGMENT_INDELETE)
{ {
MiReleasePfnLock(OldIrql);
return NULL; return NULL;
} }
MiReleasePfnLock(OldIrql);
return Result; return Result;
} }
//previous_entry = current_entry; //previous_entry = current_entry;
current_entry = current_entry->Next; current_entry = current_entry->Next;
} }
MiReleasePfnLock(OldIrql);
return NULL; return NULL;
} }