From 503cf310adb64e0c5dab003265a2ef677b90dcf4 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Wed, 14 Sep 2016 12:45:45 +0000 Subject: [PATCH] [NTOS] - Return pool quota before freeing IRPs to a lookaside list CORE-11962 #resolve svn path=/trunk/; revision=72674 --- reactos/ntoskrnl/include/internal/mm.h | 5 +++ reactos/ntoskrnl/io/iomgr/irp.c | 8 +++++ reactos/ntoskrnl/mm/ARM3/expool.c | 48 +++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index be245aac72a..866d597b9bd 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -1397,6 +1397,11 @@ ExpCheckPoolAllocation( POOL_TYPE PoolType, ULONG Tag); +VOID +NTAPI +ExReturnPoolQuota( + IN PVOID P); + /* mmsup.c *****************************************************************/ diff --git a/reactos/ntoskrnl/io/iomgr/irp.c b/reactos/ntoskrnl/io/iomgr/irp.c index e243cfc15f9..e00baf18695 100644 --- a/reactos/ntoskrnl/io/iomgr/irp.c +++ b/reactos/ntoskrnl/io/iomgr/irp.c @@ -1649,6 +1649,14 @@ IoFreeIrp(IN PIRP Irp) /* The free was within the Depth */ if (Irp) { + /* Remove the association with the process */ + if (Irp->AllocationFlags & IRP_QUOTA_CHARGED) + { + ExReturnPoolQuota(Irp); + Irp->AllocationFlags &= ~IRP_QUOTA_CHARGED; + } + + /* Add it to the lookaside list */ InterlockedPushEntrySList(&List->L.ListHead, (PSLIST_ENTRY)Irp); } diff --git a/reactos/ntoskrnl/mm/ARM3/expool.c b/reactos/ntoskrnl/mm/ARM3/expool.c index 25d3b41c6d2..503f5ea5b8c 100644 --- a/reactos/ntoskrnl/mm/ARM3/expool.c +++ b/reactos/ntoskrnl/mm/ARM3/expool.c @@ -1509,6 +1509,53 @@ ExQueryPoolUsage(OUT PULONG PagedPoolPages, *PagedPoolLookasideHits += 0; } +VOID +NTAPI +ExReturnPoolQuota(IN PVOID P) +{ + PPOOL_HEADER Entry; + POOL_TYPE PoolType; + USHORT BlockSize; + PEPROCESS Process; + + if ((ExpPoolFlags & POOL_FLAG_SPECIAL_POOL) && + (MmIsSpecialPoolAddress(P))) + { + return; + } + + Entry = P; + Entry--; + ASSERT((ULONG_PTR)Entry % POOL_BLOCK_SIZE == 0); + + PoolType = Entry->PoolType - 1; + BlockSize = Entry->BlockSize; + + if (PoolType & QUOTA_POOL_MASK) + { + Process = ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1]; + ASSERT(Process != NULL); + if (Process) + { + if (Process->Pcb.Header.Type != ProcessObject) + { + DPRINT1("Object %p is not a process. Type %u, pool type 0x%x, block size %u\n", + Process, Process->Pcb.Header.Type, Entry->PoolType, BlockSize); + KeBugCheckEx(BAD_POOL_CALLER, + 0x0D, + (ULONG_PTR)P, + Entry->PoolTag, + (ULONG_PTR)Process); + } + ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1] = NULL; + PsReturnPoolQuota(Process, + PoolType & BASE_POOL_TYPE_MASK, + BlockSize * POOL_BLOCK_SIZE); + ObDereferenceObject(Process); + } + } +} + /* PUBLIC FUNCTIONS ***********************************************************/ /* @@ -2285,7 +2332,6 @@ ExFreePoolWithTag(IN PVOID P, if ((Entry->PoolType - 1) & QUOTA_POOL_MASK) { Process = ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1]; - ASSERT(Process != NULL); if (Process) { if (Process->Pcb.Header.Type != ProcessObject)