I tracked down the source of the asserts under Checked WinXPSP2 during
MmMapLockedPages*(). I am creating an MDL for read-only kernel code VA
using IoAllocateMdl, and then call MmBuildMdlForNonPagedPool to add the
underlying physical pages to the MDL.
But, the resulting MDL has the MDL_SOURCE_IS_NONPAGED_POOL flag set, even
though the VA wasn’t alloc’ed from NPP but was part of a Non-paged code
segment. Because I can’t find a call for MmBuildMdlForNonPagedCodeSegment,
I “updated” the MDL flags by removing MDL_SOURCE_IS_NONPAGED_POOL and
adding MDL_PAGES_LOCKED. Now, I can use the MDL in MmMapLockedPages*
without problems.
This raises two questions:
First, is there a difference between non-paged and locked Virtual
addresses? If some code was originally paged, but then was locked,
would it be the same as NonPaged code (not NonPagedPool)? It seems
that NPP exists in a reserved memory range and that any non-paged
memory outside that range cannot be referred to as NonPaged “Pool”.
Second, since the “proper” system calls don’t exist for building an
MDL for non-paged but not non-paged-pool memory, what are the likely
consequences of my manipulation of MDL flags? I used the ntddk.h
struct and flag defs to minimize issues if things change, but I
doubt that Microsoft would bless this in any way. Or should I try
to find a way to build partial MDLs that eventually have the right
MDL flags?
Before you ask why I need to do this, I’m working with a major
security tool company to create a callback interface like that in
cmRegisterCallback, but for pre-process creation, termination, read,
write, etc. so that another driver (talking to a user-mode app)
can control the behavior by returning non-success in the Callback.
The official CreateProcess/Thread callbacks occur AFTER the process
creation, termination, etc., where it is too late to veto the request.
Oh, great Microsoft. If you could create back-ported callback
services for cmRegisterCallback and processRegisterCallback, you
would see a tremendous decrease in the number of drivers trying
to hook internal jump tables in the kernel. Adding them for
longhorn alone is not sufficient unless you can guarantee that all
other OS versions can be deactivated the day longhorn releases.
Suggestions, comments welcome. Flames about hooking the kernel
are not.
Jerry Schneider