Driver Verifier has a Special Pool option, which causes your pool allocations to come out of special pool and get all sorts of added checking. This includes things such as guard pages at the end of your allocations to avoid buffer overruns, checks against accessing buffers after you free them, etc. Unfortunately the !pool command in WinDBG appears to be broken when given a special pool address on Windows XP. I haven’t had the chance to investigate further on newer O/S platforms, so it’s possible that there are also some issues there.
The extension command appears to have two issues:
1) The size shown as the allocation size is really the allocation size minus 8. Take for example a verified driver that does the following:
a = ExAllocatePoolWithTag(NonPagedPool, 4, 'xxxx');
b = ExAllocatePoolWithTag(NonPagedPool, 8, 'xxxx');
c = ExAllocatePoolWithTag(NonPagedPool, 16, 'xxxx');
A !pool on a, b, and c shows the following (respectively):
1: kd> !pool 0x82a5aff8
Pool page 82a5aff8 region is Special pool
*82a5b000 size: fffffffc non-paged special pool, Tag is xxxx
Owning component : Unknown (update pooltag.txt)
1: kd> !pool 0x824eeff8
Pool page 824eeff8 region is Special pool
*824ef000 size: 0 non-paged special pool, Tag is xxxx
Owning component : Unknown (update pooltag.txt)
1: kd> !pool 0x82940ff0
Pool page 82940ff0 region is Special pool
*82940ff8 size: 8 non-paged special pool, Tag is xxxx
Owning component : Unknown (update pooltag.txt)
2) The pool header addresses are incorrect. Take a in the example above:
1: kd> !pool 0x82a5aff8
Pool page 82a5aff8 region is Special pool
*82a5b000
That address given as the pool header is actually the guard page and not the header:
1: kd> dt nt!_pool_header 82a5b000
+0x000 PreviousSize : ??
+0x000 PoolIndex : ??
+0x002 BlockSize : ??
+0x002 PoolType : ??
+0x000 Ulong1 : ??
+0x004 ProcessBilled : ????
+0x004 PoolTag : ??
+0x004 AllocatorBackTraceIndex : ??
+0x006 PoolTagHash : ??
Memory read error 82a5b006
The pool header in this case is the page rounded down to page size, not up to:
1: kd> dt nt!_pool_header 0x82a5a000
+0x000 PreviousSize : 0y000000100 (0x4)
+0x000 PoolIndex : 0y0100000 (0x20)
+0x002 BlockSize : 0y001010001 (0x51)
+0x002 PoolType : 0y0000000 (0)
+0x000 Ulong1 : 0x514004
+0x004 ProcessBilled : 0x78787878 _EPROCESS
+0x004 PoolTag : 0x78787878
+0x004 AllocatorBackTraceIndex : 0x7878
+0x006 PoolTagHash : 0x7878
As you can see, the tag is the correct “xxxx” that we specified in the allocation:
1: kd> .formats 0x78787878
Evaluate expression:
Hex: 78787878
Decimal: 2021161080
Octal: 17036074170
Binary: 01111000 01111000 01111000 01111000
Chars: xxxx
Time: Tue Jan 17 20:38:00 2034
Float: low 2.01583e+034 high 0
Double: 9.98586e-315