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
This commit is contained in:
Hartmut Birr 2005-06-05 14:01:58 +00:00
parent 00457dbaa6
commit 09b3ff1ebb
4 changed files with 115 additions and 51 deletions

View 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);

View 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;
}

View 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);
}

View 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);
}
/**********************************************************************