INFO: Introduction to Windows NT Kernel Special Pool
ID: Q192486
|
The information in this article applies to:
-
Microsoft Win32 Device Driver Kit (DDK) for Windows NT, version 4.0
-
Microsoft Windows 2000
This article discusses a Beta release of a Microsoft
product. The information in this article is provided as-is
and is subject to change without notice.
No formal product support is available from Microsoft for
this Beta product. For information about obtaining support
for a Beta release, please see the documentation included
with the Beta product files, or check the Web location
from which you downloaded the release.
SUMMARY
Kernel pool corruption has been difficult to debug in Windows NT because
typically the system crashes before you can find the culprit. Some common
causes of kernel pool corruption include:
- Code that allocates N bytes of pool and then reads or writes N+1 bytes.
- Code that frees pool and then accesses or modifies it after freeing it.
- Code that frees the same pool multiple times.
- Code that accesses memory in front of the allocation.
A new feature called Kernel Special Pool is included in Windows 2000 Beta
2 and in Windows NT 4.0 Service Pack 4, which can be used to find these
types of problems. This article describes how the Kernel Special Pool
works.
MORE INFORMATION
The "special pool" feature causes a complete page of memory to be allocated
for each request that matches the specified tag or allocation size. Kernel
Special Pool is only in effect when the requested allocation size is less
than PAGE_SIZE.
If you have overrun detection enabled (described later in this article),
you will crash if you access beyond your allocation. If you have underrun
detection enabled (described later in this article), you will crash if you
access memory before you reach your allocation. If you touch your
allocation after freeing it, you will crash. If you free your allocation
twice, you will crash (provided that the allocation has not been reused).
Unlike regular pool, which is LIFO, special pool is FIFO. Also, computers
with more memory are given a bigger range of special pool virtual
addresses. The stack at failure reflects the exact instruction that caused
the system to crash. Using the debugger, you can identify the culprit and
the information you need to fix the problem.
Kernel Special Pool catches almost all problems associated with pool
corruption, and it catches them early enough so that you can fix them
easily. Kernel Special Pool works on both the checked and free versions of
the operating system. Use Kernel Special Pool only during debugging. Do not
enable it in a production environment because it increases the amount of
pool that is used and committed (such as pagefile space) on the system.
Kernel Special Pool can also cause premature paging since the memory usage
can be much greater.
Overrun Detection vs. Underrun Detection
Overrun detection (the default) is a check to ensure that you do not access
past your memory allocation. This is accomplished by 8-byte aligning the
request to the end of the allocated page and marking the page as no-access
following the allocation. If you try to access past the end of the
allocated pool, a system trap occurs.
Underrun detection is a check to insure that you do not access memory in
front of the memory allocation. This is accomplished by aligning the
request at the beginning of the allocated page and marking the page as no-
access before the allocation. If you try to access prior to the beginning
of the allocated page, a system trap occurs.
In both cases, single-byte corruption within the alignment portion of the
page is also detected. If it exists, this slush space, which is less than
the alignment size-8 bytes, is at the end of the page for overruns or in
the rest of the page for underruns. Corruption in these portions of the
page causes a bug check upon release of the memory instead of at the time
of the bad access because these cannot be enforced using existing hardware
mechanisms.
Kernel Special Pool Characteristics
The following summarizes characteristics of the kernel special pool:
- Allocations are always in PAGE_SIZE increments for both Paged and
NonPaged pool type allocations.
- There is only one memory allocation per page.
- Allocation is 8-byte aligned to the end of the page for overrun
detection.
- Allocation is page aligned for underrun detection.
- The page following the allocation and the page before the allocation
are invalid for both overrun and underrun detection.
- When the allocation is freed, the page or pages are marked invalid
until they are reused. An LRU algorithm insures that freed pools are
not reused immediately, but obviously cannot protect the page's reuse
forever.
Methods for Specifying Pool Allocations
There are two methods that you can use to specify pool allocations:
Enabling Kernel Special Pool
There are two different ways to enable Kernel Special Pool. Each requires a
you to restart the operating system.
Pool Corruption Debugging Strategies
You might need to focus on a specific pool tag if it looks like the
beginning or end of your allocation is corrupted. For a corruption at the
beginning, you have to find the tag of the allocation before the corrupted
one and focus on it. For a corruption at the end, you have to find the tag
of the allocation after the corrupted one and focus on it. It might be
difficult to find the correct tag for an overrun, because the corruption
will likely invalidate the pool header that has control information.
If you are unsure of the corrupting component, but you are sure of the
allocation size that is causing problems, you can set the PoolTag value in
the registry to the size that corresponds to the size range that the
corrupter might be using. If you do this, memory management will allocate
these blocks in the special pool. Look at the header prior to the one you
think is corrupted. That might be the one that is overwriting past the end
of its allocation and corrupting your allocation. If the end of your pool
allocation seems corrupted (possibly caused by the next allocation writing
backward over your allocation), then you can set PoolTag to the size of the
next block and also set PoolTagOverruns to zero to enable underrun
detection.
Debugging Failures for Special Pool
If some kernel component writes beyond the limit of the block allocated, a
memory fault occurs. The typical bug check is 0x50
(PAGE_FAULT_IN_NONPAGED_AREA) or 0xA (IRQL_NOT_LESS_OR_EQUAL) and the top
of the stack should be similar to the following:
ntkrnlmp!RtlpBreakWithStatusInstruction
ntkrnlmp!KeBugCheckEx+[ASCII 133]
ntkrnlmp!MmAccessFault+[ASCII 133]
ntkrnlmp!KiTrap0E+[ASCII 133]
Module!Function ...
This indicates a high probability that the "Module" code accesses memory
beyond what is allocated.
Conclusion
- Use Kernel Special Pool to catch driver memory problems before you
release your driver.
- Use ExAllocatePoolWithTag to allocate memory, rather then
ExAllocatePool. Choose useful, unique tag values.
- Use the kernel debugger and become familiar with debugging driver
problems.
REFERENCES
See the Windows NT DDK for additional driver and debugging information.
Keywords : kbDDK kbDebug kbNTOS400 kbWinOS2000
Version :
Platform :
Issue type : kbinfo
Last Reviewed: March 5, 1999