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/…
==============================================================================
--- 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=…
==============================================================================
--- 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(a)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=407…
==============================================================================
--- 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.…
==============================================================================
--- 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>