Introduction
Kernel-mode drivers in Windows must strictly adhere to memory access rules to prevent system instability. A common issue arises when drivers improperly access user-mode memory, leading to catastrophic failures such as PAGE_FAULT_IN_NONPAGED_AREA or system-wide crashes. This post explores the symptoms, root cause, and resolution of such violations, focusing on low-level debugging and mitigation techniques.
Symptoms of the Issue
Users may experience the following symptoms:
- Blue Screen of Death (BSOD) with code
PAGE_FAULT_IN_NONPAGED_AREA
- Random system crashes during high I/O or application interactions
- Application hangs or unexpected termination due to driver-level corruption
- Log entries in the Windows Event Viewer indicating driver exceptions
Root Cause Analysis
The root cause typically involves a driver accessing user-mode memory (e.g., buffers allocated by user-space applications) without proper validation. Windows enforces strict separation between user-mode and kernel-mode memory, and direct access to user buffers without verification triggers a page fault. For example, a driver might misuse CopyMemory
or memcpy
on a user-provided pointer without first checking if the address is valid or accessible via ProbeForRead
or ProbeForWrite
. This leads to the system crashing when the driver accesses invalid or protected memory regions.
Example Code Demonstrating the Problem
NTSTATUS MyDriverDispatchRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PVOID userBuffer = irpStack->Parameters.DeviceIoControl.InputBuffer;
ULONG bufferSize = irpStack->Parameters.DeviceIoControl.InputBufferSize;
// Improperly access user-mode memory without validation
memcpy(kernelBuffer, userBuffer, bufferSize); // Direct user buffer access
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = bufferSize;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
This code violates kernel-mode memory safety by assuming userBuffer is valid without probing. If the pointer points to invalid memory, the system crashes.
Diagnosis Tools and Techniques
Use the following tools to identify the issue:
- Windows Debugger (WinDbg): Analyze memory dumps to locate the faulty driver and stack trace.
- Process Monitor (ProcMon): Track file and registry access patterns to identify abnormal interactions.
- Driver Verifier: Enable memory integrity checks for drivers to force the system to crash earlier, exposing the violation.
- !analyze -v command in WinDbg: Decode the BSOD and pinpoint the driver and function responsible.
- !pte command: Inspect page table entries to confirm user-mode memory accessibility.
Step-by-Step Resolution
1. Capture a memory dump using !dumpfile
in WinDbg after a crash.
2. Run !analyze -v
to identify the driver and function implicated in the fault.
3. Use !drvobj
to locate the driver’s source code and check for raw user buffer access.
4. Replace direct buffer access with ProbeForRead
or ProbeForWrite
to validate the user pointer:
NTSTATUS MyDriverDispatchRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PVOID userBuffer = irpStack->Parameters.DeviceIoControl.InputBuffer;
ULONG bufferSize = irpStack->Parameters.DeviceIoControl.InputBufferSize;
// Validate user buffer access
if (bufferSize > 0) {
ProbeForRead(userBuffer, bufferSize, sizeof(ULONG));
}
// Proceed with safe copying
memcpy(kernelBuffer, userBuffer, bufferSize);
// ...
}
5. Test the driver with Driver Verifier
enabled to ensure compliance.
6. Rebuild and deploy the driver, monitoring logs and system stability.
7. If the issue persists, use !object
in WinDbg to inspect the IRP and device object for anomalies.
Conclusion
Kernel-mode drivers must enforce strict memory validation when handling user-provided data. By leveraging tools like WinDbg and adopting safe practices such as ProbeForRead
, administrators and developers can mitigate crashes and ensure system stability. Always validate user-mode pointers to prevent violations of Windows’ memory protection mechanisms.