- Implement a special "debug pool" allocator which catches pool overruns. It evolved from an initial patch by Art Yerkes, and is fully independent from underlying pool implementation. It supports only non-paged pool and detects only overruns now. To enable, uncomment DEBUG_NPOOL define in mm/pool.c.

svn path=/trunk/; revision=40726
This commit is contained in:
Aleksey Bragin 2009-04-29 09:41:32 +00:00
parent d8d8b19d4a
commit eb036429b8
4 changed files with 152 additions and 2 deletions

View file

@ -558,6 +558,24 @@ VOID
NTAPI
ExFreePagedPool(IN PVOID Block);
BOOLEAN
NTAPI
ExpIsPoolTagDebuggable(ULONG Tag);
PVOID
NTAPI
ExpAllocateDebugPool(
POOL_TYPE Type,
ULONG Size,
ULONG Tag,
PVOID Caller,
BOOLEAN EndOfPage
);
VOID
NTAPI
ExpFreeDebugPool(PVOID Block);
VOID
NTAPI
MmInitializePagedPool(VOID);

View file

@ -0,0 +1,117 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/mm/dbgpool.c
* PURPOSE: Debug version of a pool allocator
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES ***************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS **************************************************************/
typedef struct _EI_WHOLE_PAGE_HEADER {
PVOID ActualAddress;
ULONG Size;
ULONG Tag;
} EI_WHOLE_PAGE_HEADER, *PEI_WHOLE_PAGE_HEADER;
BOOLEAN
NTAPI
ExpIsPoolTagDebuggable(ULONG Tag)
{
if (Tag == TAG('C', 'a', 'l', 'l')) return FALSE;
if (Tag == TAG('D', 'r', 'i', 'v')) return FALSE;
if (Tag == TAG('D', 'e', 'v', 'i')) return FALSE;
if (Tag == TAG('A', 'd', 'a', 'p')) return FALSE;
return FALSE;//TRUE;
}
PVOID
NTAPI
ExpAllocateDebugPool(POOL_TYPE Type, ULONG Size, ULONG Tag, PVOID Caller, BOOLEAN EndOfPage)
{
ULONG UserSize = Size + sizeof(EI_WHOLE_PAGE_HEADER);
ULONG TotalSize = UserSize + 2*PAGE_SIZE;
ULONG_PTR UserData, GuardArea;
PEI_WHOLE_PAGE_HEADER Header;
ULONG_PTR Buffer;
/* Right now we support only end-of-page allocations */
ASSERT(EndOfPage);
/* Allocate space using default routine */
if (Type & PAGED_POOL_MASK)
{
Buffer = (ULONG_PTR)
ExAllocatePagedPoolWithTag(Type, TotalSize, Tag);
}
else
{
Buffer = (ULONG_PTR)
ExAllocateNonPagedPoolWithTag(Type, TotalSize, Tag, Caller);
}
/* If allocation failed - fail too */
if (!Buffer)
{
DPRINT1("A big problem! Pool allocation failed!\n");
return NULL;
}
/* Calculate guard area as placed on a page boundary
* at the end of allocated area */
GuardArea = PAGE_ROUND_DOWN(Buffer + TotalSize - PAGE_SIZE + 1);
/* Calculate user data and header pointers */
UserData = GuardArea - Size;
Header = (PEI_WHOLE_PAGE_HEADER)(UserData - sizeof(EI_WHOLE_PAGE_HEADER));
/* Fill out the header */
Header->ActualAddress = (PVOID)Buffer;
Header->Tag = Tag;
Header->Size = Size;
/* Protect the guard page */
MmSetPageProtect(NULL, (PVOID)GuardArea, PAGE_NOACCESS);
DPRINT1("Allocating whole page block Tag %c%c%c%c, Buffer %p, Header %p, UserData %p, GuardArea %p, Size %d\n",
Tag & 0xFF, (Tag >> 8) & 0xFF,
(Tag >> 16) & 0xFF, (Tag >> 24) & 0xFF,
Buffer, Header, UserData, GuardArea, Size);
return (PVOID)UserData;
}
VOID
NTAPI
ExpFreeDebugPool(PVOID Block)
{
PEI_WHOLE_PAGE_HEADER Header;
PVOID ProtectedPage;
/* Get pointer to our special header */
Header = (PEI_WHOLE_PAGE_HEADER)
(((PCHAR)Block) - sizeof(EI_WHOLE_PAGE_HEADER));
DPRINT1("Freeing whole page block at %08x (Tag %c%c%c%c, %x Header %x)\n", Block,
Header->Tag & 0xFF, (Header->Tag >> 8) & 0xFF,
(Header->Tag >> 16) & 0xFF, (Header->Tag >> 24) & 0xFF, Header->Tag, Header);
/* Calculate protected page adresss */
ProtectedPage = ((PCHAR)Block) + Header->Size;
/* Unprotect it */
MmSetPageProtect(NULL, ProtectedPage, PAGE_READWRITE);
/* Free storage */
ExFreeNonPagedPool(Header->ActualAddress);
}
/* EOF */

View file

@ -14,6 +14,10 @@
#define NDEBUG
#include <debug.h>
/* Uncomment to enable pool overruns debugging */
//#define DEBUG_NPOOL
//#define DEBUG_PPOOL
extern PVOID MiNonPagedPoolStart;
extern ULONG MiNonPagedPoolLength;
extern ULONG MmTotalPagedPoolQuota;
@ -60,7 +64,12 @@ EiAllocatePool(POOL_TYPE PoolType,
{
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
KeBugCheckEx(BAD_POOL_CALLER, 0x08, KeGetCurrentIrql(), PoolType, Tag);
Block = ExAllocateNonPagedPoolWithTag(PoolType, NumberOfBytes, Tag, Caller);
#ifdef DEBUG_NPOOL
if (ExpIsPoolTagDebuggable(Tag))
Block = ExpAllocateDebugPool(PoolType, NumberOfBytes, Tag, Caller, TRUE);
else
#endif
Block = ExAllocateNonPagedPoolWithTag(PoolType, NumberOfBytes, Tag, Caller);
}
if ((PoolType & MUST_SUCCEED_POOL_MASK) && !Block)
@ -292,7 +301,12 @@ ExFreePoolWithTag(
(ULONG_PTR)Block);
/* Free from non-paged pool */
ExFreeNonPagedPool(Block);
#ifdef DEBUG_NPOOL
if (ExpIsPoolTagDebuggable(Tag))
ExpFreeDebugPool(Block);
else
#endif
ExFreeNonPagedPool(Block);
}
else
{

View file

@ -362,6 +362,7 @@
<file>anonmem.c</file>
<file>balance.c</file>
<file>cont.c</file>
<file>dbgpool.c</file>
<file>drvlck.c</file>
<file>freelist.c</file>
<file>hypermap.c</file>