mirror of
https://github.com/reactos/reactos.git
synced 2025-08-01 23:53:07 +00:00
- 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:
parent
d8d8b19d4a
commit
eb036429b8
4 changed files with 152 additions and 2 deletions
|
@ -558,6 +558,24 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
ExFreePagedPool(IN PVOID Block);
|
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
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmInitializePagedPool(VOID);
|
MmInitializePagedPool(VOID);
|
||||||
|
|
117
reactos/ntoskrnl/mm/dbgpool.c
Normal file
117
reactos/ntoskrnl/mm/dbgpool.c
Normal 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 */
|
|
@ -14,6 +14,10 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
/* Uncomment to enable pool overruns debugging */
|
||||||
|
//#define DEBUG_NPOOL
|
||||||
|
//#define DEBUG_PPOOL
|
||||||
|
|
||||||
extern PVOID MiNonPagedPoolStart;
|
extern PVOID MiNonPagedPoolStart;
|
||||||
extern ULONG MiNonPagedPoolLength;
|
extern ULONG MiNonPagedPoolLength;
|
||||||
extern ULONG MmTotalPagedPoolQuota;
|
extern ULONG MmTotalPagedPoolQuota;
|
||||||
|
@ -60,7 +64,12 @@ EiAllocatePool(POOL_TYPE PoolType,
|
||||||
{
|
{
|
||||||
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
|
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
|
||||||
KeBugCheckEx(BAD_POOL_CALLER, 0x08, KeGetCurrentIrql(), PoolType, Tag);
|
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)
|
if ((PoolType & MUST_SUCCEED_POOL_MASK) && !Block)
|
||||||
|
@ -292,7 +301,12 @@ ExFreePoolWithTag(
|
||||||
(ULONG_PTR)Block);
|
(ULONG_PTR)Block);
|
||||||
|
|
||||||
/* Free from non-paged pool */
|
/* Free from non-paged pool */
|
||||||
ExFreeNonPagedPool(Block);
|
#ifdef DEBUG_NPOOL
|
||||||
|
if (ExpIsPoolTagDebuggable(Tag))
|
||||||
|
ExpFreeDebugPool(Block);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ExFreeNonPagedPool(Block);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -362,6 +362,7 @@
|
||||||
<file>anonmem.c</file>
|
<file>anonmem.c</file>
|
||||||
<file>balance.c</file>
|
<file>balance.c</file>
|
||||||
<file>cont.c</file>
|
<file>cont.c</file>
|
||||||
|
<file>dbgpool.c</file>
|
||||||
<file>drvlck.c</file>
|
<file>drvlck.c</file>
|
||||||
<file>freelist.c</file>
|
<file>freelist.c</file>
|
||||||
<file>hypermap.c</file>
|
<file>hypermap.c</file>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue