Don't lock the kernel address space while solving faults from the paged pool.
authorHartmut Birr <osexpert@googlemail.com>
Sun, 5 Jun 2005 14:01:58 +0000 (14:01 +0000)
committerHartmut Birr <osexpert@googlemail.com>
Sun, 5 Jun 2005 14:01:58 +0000 (14:01 +0000)
It is possible, that someone try to access memory from paged pool
while the kernel address space is already locked.

svn path=/trunk/; revision=15805

reactos/ntoskrnl/include/internal/mm.h
reactos/ntoskrnl/mm/mdl.c
reactos/ntoskrnl/mm/mm.c
reactos/ntoskrnl/mm/ppool.c

index 1821334..e579470 100644 (file)
@@ -367,6 +367,9 @@ typedef VOID (*PMM_FREE_PAGE_FUNC)(PVOID Context, PMEMORY_AREA MemoryArea,
 
 /* FUNCTIONS */
 
+VOID MmLockPagedPool(VOID);
+VOID MmUnlockPagedPool(VOID);
+
 /* aspace.c ******************************************************************/
 
 VOID MmLockAddressSpace(PMADDRESS_SPACE AddressSpace);
index d51fefd..c8f740d 100644 (file)
@@ -364,6 +364,7 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
    PFN_TYPE Page;
    PEPROCESS CurrentProcess = PsGetCurrentProcess();
    PMADDRESS_SPACE AddressSpace;
+   BOOLEAN PagedPool;
 
    DPRINT("MmProbeAndLockPages(Mdl %x)\n", Mdl);
 
@@ -398,6 +399,7 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
       Mode = KernelMode;
       Mdl->Process = NULL;
       AddressSpace = MmGetKernelAddressSpace();
+      PagedPool = Mdl->StartVa >= MmPagedPoolBase && Mdl->StartVa < MmPagedPoolBase + MmPagedPoolSize ? TRUE : FALSE;
    }
    else
    {
@@ -405,14 +407,21 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
       Mode = UserMode;
       Mdl->Process = CurrentProcess;
       AddressSpace = &CurrentProcess->AddressSpace;
+      PagedPool = FALSE;
    }
 
+   if (PagedPool)
+   {
+      MmLockPagedPool();
+   }
+   else
+   {
+      MmLockAddressSpace(AddressSpace);
+   }
 
    /*
     * Lock the pages
     */
-   MmLockAddressSpace(AddressSpace);
-
    for (i = 0; i < NrPages; i++)
    {
       PVOID Address;
@@ -438,7 +447,14 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
                   MmDereferencePage(Page);
                }
             }
-            MmUnlockAddressSpace(AddressSpace);
+            if (PagedPool)
+            {
+               MmUnlockPagedPool();
+            }
+            else
+            {
+               MmUnlockAddressSpace(AddressSpace);
+            }
             ExRaiseStatus(STATUS_ACCESS_VIOLATION);
          }
       }
@@ -462,7 +478,14 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
                   MmDereferencePage(Page);
                }
             }
-            MmUnlockAddressSpace(AddressSpace);
+            if (PagedPool)
+            {
+               MmUnlockPagedPool();
+            }
+            else
+            {
+               MmUnlockAddressSpace(AddressSpace);
+            }
             ExRaiseStatus(STATUS_ACCESS_VIOLATION);
          }
       }
@@ -474,7 +497,14 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
          MmReferencePage(Page);
    }
 
-   MmUnlockAddressSpace(AddressSpace);
+   if (PagedPool)
+   {
+      MmUnlockPagedPool();
+   }
+   else
+   {
+      MmUnlockAddressSpace(AddressSpace);
+   }
    Mdl->MdlFlags |= MDL_PAGES_LOCKED;
 }
 
index 5a54dbc..9db3c36 100644 (file)
@@ -215,6 +215,10 @@ NTSTATUS MmAccessFault(KPROCESSOR_MODE Mode,
          DbgPrint("%s:%d\n",__FILE__,__LINE__);
          return(STATUS_UNSUCCESSFUL);
       }
+      if (Address >= (ULONG_PTR)MmPagedPoolBase && Address < (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize)
+      {
+         return STATUS_SUCCESS;
+      }
       AddressSpace = MmGetKernelAddressSpace();
    }
    else
@@ -285,9 +289,7 @@ NTSTATUS MmCommitPagedPoolAddress(PVOID Address, BOOLEAN Locked)
    Status = MmRequestPageMemoryConsumer(MC_PPOOL, FALSE, &AllocatedPage);
    if (!NT_SUCCESS(Status))
    {
-      MmUnlockAddressSpace(MmGetKernelAddressSpace());
-      Status = MmRequestPageMemoryConsumer(MC_PPOOL, TRUE, &AllocatedPage);
-      MmLockAddressSpace(MmGetKernelAddressSpace());
+      return Status;
    }
    Status =
       MmCreateVirtualMapping(NULL,
@@ -311,6 +313,7 @@ NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
    NTSTATUS Status;
    BOOLEAN Locked = FromMdl;
    PFN_TYPE Pfn;
+   BOOLEAN PagedPool;
 
    DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address);
 
@@ -344,16 +347,25 @@ NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
         CPRINT("Address: %x\n", Address);
          return(STATUS_UNSUCCESSFUL);
       }
+      PagedPool = Address >= (ULONG_PTR)MmPagedPoolBase && Address < (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize ? TRUE : FALSE;
       AddressSpace = MmGetKernelAddressSpace();
    }
    else
    {
+      PagedPool = FALSE;
       AddressSpace = &PsGetCurrentProcess()->AddressSpace;
    }
 
    if (!FromMdl)
    {
-      MmLockAddressSpace(AddressSpace);
+      if (PagedPool)
+      {
+         MmLockPagedPool();
+      }
+      else
+      {
+         MmLockAddressSpace(AddressSpace);
+      }
    }
 
    /*
@@ -361,56 +373,56 @@ NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
     */
    do
    {
-      MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
-      if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
+      if (PagedPool)
       {
-         if (!FromMdl)
-         {
-            MmUnlockAddressSpace(AddressSpace);
-         }
-         return (STATUS_UNSUCCESSFUL);
+         Status = MmCommitPagedPoolAddress((PVOID)Address, Locked);
       }
-
-      switch (MemoryArea->Type)
+      else
       {
-         case MEMORY_AREA_PAGED_POOL:
+         MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
+         if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
+         {
+            if (!FromMdl)
             {
-               Status = MmCommitPagedPoolAddress((PVOID)Address, Locked);
-               break;
+               MmUnlockAddressSpace(AddressSpace);
             }
+            return (STATUS_UNSUCCESSFUL);
+         }
 
-         case MEMORY_AREA_SYSTEM:
-            Status = STATUS_UNSUCCESSFUL;
-            break;
+         switch (MemoryArea->Type)
+         {
+            case MEMORY_AREA_SYSTEM:
+               Status = STATUS_UNSUCCESSFUL;
+               break;
 
-         case MEMORY_AREA_SECTION_VIEW:
-            Status = MmNotPresentFaultSectionView(AddressSpace,
-                                                  MemoryArea,
-                                                  (PVOID)Address,
-                                                  Locked);
-            break;
+            case MEMORY_AREA_SECTION_VIEW:
+               Status = MmNotPresentFaultSectionView(AddressSpace,
+                                                     MemoryArea,
+                                                     (PVOID)Address,
+                                                     Locked);
+               break;
 
-         case MEMORY_AREA_VIRTUAL_MEMORY:
-         case MEMORY_AREA_PEB_OR_TEB:
-            Status = MmNotPresentFaultVirtualMemory(AddressSpace,
-                                                    MemoryArea,
-                                                    (PVOID)Address,
-                                                    Locked);
-            break;
+            case MEMORY_AREA_VIRTUAL_MEMORY:
+            case MEMORY_AREA_PEB_OR_TEB:
+               Status = MmNotPresentFaultVirtualMemory(AddressSpace,
+                                                       MemoryArea,
+                                                       (PVOID)Address,
+                                                       Locked);
+               break;
 
-         case MEMORY_AREA_SHARED_DATA:
-           Pfn = MmSharedDataPagePhysicalAddress.QuadPart >> PAGE_SHIFT;
-            Status =
-               MmCreateVirtualMapping(PsGetCurrentProcess(),
-                                      (PVOID)PAGE_ROUND_DOWN(Address),
-                                      PAGE_READONLY,
-                                      &Pfn,
-                                      1);
-            break;
+            case MEMORY_AREA_SHARED_DATA:
+              Pfn = MmSharedDataPagePhysicalAddress.QuadPart >> PAGE_SHIFT;
+               Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
+                                               (PVOID)PAGE_ROUND_DOWN(Address),
+                                               PAGE_READONLY,
+                                               &Pfn,
+                                               1);
+               break;
 
-         default:
-            Status = STATUS_UNSUCCESSFUL;
-            break;
+            default:
+               Status = STATUS_UNSUCCESSFUL;
+               break;
+         }
       }
    }
    while (Status == STATUS_MM_RESTART_OPERATION);
@@ -418,7 +430,14 @@ NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
    DPRINT("Completed page fault handling\n");
    if (!FromMdl)
    {
-      MmUnlockAddressSpace(AddressSpace);
+      if (PagedPool)
+      {
+         MmUnlockPagedPool();
+      }
+      else
+      {
+         MmUnlockAddressSpace(AddressSpace);
+      }
    }
    return(Status);
 }
index 767b739..14fe1af 100644 (file)
@@ -41,11 +41,12 @@ PVOID MmPagedPoolBase;
 ULONG MmPagedPoolSize;
 ULONG MmTotalPagedPoolQuota = 0; // TODO FIXME commented out until we use it
 static PR_POOL MmPagedPool = NULL;
+static FAST_MUTEX MmPagedPoolLock;
 
 /* FUNCTIONS *****************************************************************/
 
 VOID INIT_FUNCTION
-MmInitializePagedPool()
+MmInitializePagedPool(VOID)
 {
        /*
         * We are still at a high IRQL level at this point so explicitly commit
@@ -60,6 +61,17 @@ MmInitializePagedPool()
                PAGE_SIZE );
 
        ExInitializeFastMutex(&MmPagedPool->Mutex);
+        ExInitializeFastMutex(&MmPagedPoolLock);
+}
+
+VOID MmLockPagedPool(VOID)
+{
+   ExAcquireFastMutex(&MmPagedPoolLock);
+}
+
+VOID MmUnlockPagedPool(VOID)
+{
+   ExReleaseFastMutex(&MmPagedPoolLock);
 }
 
 /**********************************************************************