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/mm.h?rev=40726&r1=40725&r2=40726&view=diff
==============================================================================
--- 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=40726&view=auto
==============================================================================
--- 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 ([email protected])
+ */
+
+/* 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=40726&r1=40725&r2=40726&view=diff
==============================================================================
--- 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.rbuild?rev=40726&r1=40725&r2=40726&view=diff
==============================================================================
--- 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>

Reply via email to