https://git.reactos.org/?p=reactos.git;a=commitdiff;h=bec42b653031205a37567179ba6a70bce8fcfb02

commit bec42b653031205a37567179ba6a70bce8fcfb02
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Fri May 21 15:11:50 2021 +0200
Commit:     Jérôme Gardou <[email protected]>
CommitDate: Fri Jun 25 10:28:51 2021 +0200

    [NTOS:MM] Do not call ExAllocatePool* with PFN lock acquired
    
    Unsurprisingly, it actually might acquire it
---
 ntoskrnl/mm/section.c | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c
index b6a6ca67b4c..d758e8d3de0 100644
--- a/ntoskrnl/mm/section.c
+++ b/ntoskrnl/mm/section.c
@@ -2385,6 +2385,7 @@ MmCreateDataFileSection(PSECTION *SectionObject,
     }
 
     /* Lock the PFN lock while messing with Section Object pointers */
+grab_segment:
     OldIrql = MiAcquirePfnLock();
     Segment = FileObject->SectionObjectPointer->DataSectionObject;
 
@@ -2402,12 +2403,14 @@ MmCreateDataFileSection(PSECTION *SectionObject,
      */
     if (Segment == NULL)
     {
+        /* Release the lock. ExAllocatePoolWithTag might acquire it */
+        MiReleasePfnLock(OldIrql);
+
         Segment = ExAllocatePoolWithTag(NonPagedPool, 
sizeof(MM_SECTION_SEGMENT),
                                         TAG_MM_SECTION_SEGMENT);
         if (Segment == NULL)
         {
             //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
-            MiReleasePfnLock(OldIrql);
             ObDereferenceObject(Section);
             return STATUS_NO_MEMORY;
         }
@@ -2417,6 +2420,17 @@ MmCreateDataFileSection(PSECTION *SectionObject,
         Segment->SegFlags = MM_DATAFILE_SEGMENT | MM_SEGMENT_INCREATE;
         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;
 
         /* We're safe to release the lock now */
@@ -3160,6 +3174,7 @@ MmCreateImageSection(PSECTION *SectionObject,
     if (AllocationAttributes & SEC_NO_CHANGE)
         Section->u.Flags.NoChange = 1;
 
+grab_image_section_object:
     OldIrql = MiAcquirePfnLock();
 
     /* Wait for it to be properly created or deleted */
@@ -3178,16 +3193,28 @@ MmCreateImageSection(PSECTION *SectionObject,
     {
         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);
         if (ImageSectionObject == NULL)
         {
-            MiReleasePfnLock(OldIrql);
             ObDereferenceObject(Section);
             return STATUS_NO_MEMORY;
         }
 
         ImageSectionObject->SegFlags = MM_SEGMENT_INCREATE;
         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;
 
         MiReleasePfnLock(OldIrql);

Reply via email to