Uninformed: Informative Information for the Uninformed

Vol 4» 2006.Jun

Locking Memory

When accessing arbitrary memory locations, it is important that pages be locked in memory prior to accessing them. This is done to ensure that accessing the page can be done safely and will not cause an exception due to a race condition, such as if it were to be de-allocated between a check and a reference. The system provides a routine to lock pages named nt!MmProbeAndLockPages. This routine can be used to lock either pagable or non-paged memory. Since physical pages maintain a reference count in the nt!MmPfnDatabase there is no worry of an outside source unlocking the pages and having them page out to disk or become invalid.

In order to use MmProbeAndLockPages, a caller must first build an MDL structure using something such as nt!IoAllocateMdl or nt!MmInitializeMdl. The MDL creation routines are passed a virtual address and length describing the block of virtual memory to be referenced. On a successful call to nt!MmProbeAndLockPages, the virtual address range described by the MDL structure is safe to access. Once the block is no longer needed to be accessed, the pages must be unlocked using nt!MmUnlockPages.

A trick can be used to further reduce the number of pages locked when enumerating the NonPagedPool. As documented, MmProbeAndLockPages can be called at DISPATCH_LEVEL with the limitation of it only being allowed to lock resident memory pages and failing otherwise, which is a desirable side-effect in this case.