[NTOS:MM] Do not call ExAllocatePool* with PFN lock acquired

Unsurprisingly, it actually might acquire it
This commit is contained in:
Jérôme Gardou 2021-05-21 15:11:50 +02:00 committed by Jérôme Gardou
parent 42e111f26b
commit bec42b6530

View file

@ -2385,6 +2385,7 @@ MmCreateDataFileSection(PSECTION *SectionObject,
} }
/* Lock the PFN lock while messing with Section Object pointers */ /* Lock the PFN lock while messing with Section Object pointers */
grab_segment:
OldIrql = MiAcquirePfnLock(); OldIrql = MiAcquirePfnLock();
Segment = FileObject->SectionObjectPointer->DataSectionObject; Segment = FileObject->SectionObjectPointer->DataSectionObject;
@ -2402,12 +2403,14 @@ MmCreateDataFileSection(PSECTION *SectionObject,
*/ */
if (Segment == NULL) if (Segment == NULL)
{ {
/* Release the lock. ExAllocatePoolWithTag might acquire it */
MiReleasePfnLock(OldIrql);
Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT), Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
TAG_MM_SECTION_SEGMENT); TAG_MM_SECTION_SEGMENT);
if (Segment == NULL) if (Segment == NULL)
{ {
//KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE); //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
MiReleasePfnLock(OldIrql);
ObDereferenceObject(Section); ObDereferenceObject(Section);
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
} }
@ -2417,6 +2420,17 @@ MmCreateDataFileSection(PSECTION *SectionObject,
Segment->SegFlags = MM_DATAFILE_SEGMENT | MM_SEGMENT_INCREATE; Segment->SegFlags = MM_DATAFILE_SEGMENT | MM_SEGMENT_INCREATE;
Segment->RefCount = 1; Segment->RefCount = 1;
/* Acquire lock again */
OldIrql = MiAcquirePfnLock();
if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
{
/* Well that's bad luck. Restart it all over */
MiReleasePfnLock(OldIrql);
ExFreePoolWithTag(Segment, TAG_MM_SECTION_SEGMENT);
goto grab_segment;
}
FileObject->SectionObjectPointer->DataSectionObject = Segment; FileObject->SectionObjectPointer->DataSectionObject = Segment;
/* We're safe to release the lock now */ /* We're safe to release the lock now */
@ -3160,6 +3174,7 @@ MmCreateImageSection(PSECTION *SectionObject,
if (AllocationAttributes & SEC_NO_CHANGE) if (AllocationAttributes & SEC_NO_CHANGE)
Section->u.Flags.NoChange = 1; Section->u.Flags.NoChange = 1;
grab_image_section_object:
OldIrql = MiAcquirePfnLock(); OldIrql = MiAcquirePfnLock();
/* Wait for it to be properly created or deleted */ /* Wait for it to be properly created or deleted */
@ -3178,16 +3193,28 @@ MmCreateImageSection(PSECTION *SectionObject,
{ {
NTSTATUS StatusExeFmt; NTSTATUS StatusExeFmt;
/* Release the lock because ExAllocatePoolWithTag could need to acquire it */
MiReleasePfnLock(OldIrql);
ImageSectionObject = ExAllocatePoolZero(NonPagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT); ImageSectionObject = ExAllocatePoolZero(NonPagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT);
if (ImageSectionObject == NULL) if (ImageSectionObject == NULL)
{ {
MiReleasePfnLock(OldIrql);
ObDereferenceObject(Section); ObDereferenceObject(Section);
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
} }
ImageSectionObject->SegFlags = MM_SEGMENT_INCREATE; ImageSectionObject->SegFlags = MM_SEGMENT_INCREATE;
ImageSectionObject->RefCount = 1; ImageSectionObject->RefCount = 1;
OldIrql = MiAcquirePfnLock();
if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
{
MiReleasePfnLock(OldIrql);
/* Bad luck. Start over */
ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
goto grab_image_section_object;
}
FileObject->SectionObjectPointer->ImageSectionObject = ImageSectionObject; FileObject->SectionObjectPointer->ImageSectionObject = ImageSectionObject;
MiReleasePfnLock(OldIrql); MiReleasePfnLock(OldIrql);