From 09b3ff1ebbaced9001c43ea97141c9f0ad948eaf Mon Sep 17 00:00:00 2001 From: Hartmut Birr Date: Sun, 5 Jun 2005 14:01:58 +0000 Subject: [PATCH] Don't lock the kernel address space while solving faults from the paged pool. 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 | 3 + reactos/ntoskrnl/mm/mdl.c | 40 +++++++-- reactos/ntoskrnl/mm/mm.c | 109 +++++++++++++++---------- reactos/ntoskrnl/mm/ppool.c | 14 +++- 4 files changed, 115 insertions(+), 51 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 18213340fae..e579470b87c 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -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); diff --git a/reactos/ntoskrnl/mm/mdl.c b/reactos/ntoskrnl/mm/mdl.c index d51fefd5c69..c8f740df7e9 100644 --- a/reactos/ntoskrnl/mm/mdl.c +++ b/reactos/ntoskrnl/mm/mdl.c @@ -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; } diff --git a/reactos/ntoskrnl/mm/mm.c b/reactos/ntoskrnl/mm/mm.c index 5a54dbcb857..9db3c362f5e 100644 --- a/reactos/ntoskrnl/mm/mm.c +++ b/reactos/ntoskrnl/mm/mm.c @@ -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); } diff --git a/reactos/ntoskrnl/mm/ppool.c b/reactos/ntoskrnl/mm/ppool.c index 767b739b3b8..14fe1af7fc2 100644 --- a/reactos/ntoskrnl/mm/ppool.c +++ b/reactos/ntoskrnl/mm/ppool.c @@ -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); } /**********************************************************************