Author: fireball Date: Wed Apr 29 13:41:32 2009 New Revision: 40726
URL: http://svn.reactos.org/svn/reactos?rev=40726&view=rev Log: - 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.
Added: trunk/reactos/ntoskrnl/mm/dbgpool.c (with props) Modified: trunk/reactos/ntoskrnl/include/internal/mm.h trunk/reactos/ntoskrnl/mm/pool.c trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/m... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] Wed Apr 29 13:41:32 2009 @@ -558,6 +558,24 @@ 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);
Added: trunk/reactos/ntoskrnl/mm/dbgpool.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/dbgpool.c?rev=4... ============================================================================== --- trunk/reactos/ntoskrnl/mm/dbgpool.c (added) +++ trunk/reactos/ntoskrnl/mm/dbgpool.c [iso-8859-1] Wed Apr 29 13:41:32 2009 @@ -1,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 */
Propchange: trunk/reactos/ntoskrnl/mm/dbgpool.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/ntoskrnl/mm/pool.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/pool.c?rev=4072... ============================================================================== --- trunk/reactos/ntoskrnl/mm/pool.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/pool.c [iso-8859-1] Wed Apr 29 13:41:32 2009 @@ -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 @@ { 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 @@ (ULONG_PTR)Block);
/* Free from non-paged pool */ - ExFreeNonPagedPool(Block); +#ifdef DEBUG_NPOOL + if (ExpIsPoolTagDebuggable(Tag)) + ExpFreeDebugPool(Block); + else +#endif + ExFreeNonPagedPool(Block); } else {
Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.r... ============================================================================== --- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Wed Apr 29 13:41:32 2009 @@ -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>