I’m trying to maintain an old driver and have run into a strange issue when the driver tries to handle an IOCTL sent by a user mode application.
The driver runs fine when the 32-bit driver is called by a 32-bit app, or the 64-bit driver is called by a 32-bit app.
However it blue-screens occasionally in case?the 64-bit driver is called by a 64-bit app.
(Contents below have been slightly modified to remove meaningful method names, product names, and such)
The bugcheck analysis looks like this:
18: kd> !analyze -v
PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. ?This cannot be protected by try-except,
it must be protected by a Probe. ?Typically the address is just plain bad or it
is pointing at freed memory.
Arguments:
Arg1: ffffffff91ae00e0, memory referenced.
Arg2: 0000000000000000, value 0 = read operation, 1 = write operation.
Arg3: fffff800016a7b38, If non-zero, the instruction address which referenced the bad memory
address.
Arg4: 0000000000000005, (reserved)
Debugging Details:
READ_ADDRESS: ?ffffffff91ae00e0?
FAULTING_IP:?
nt!MmProbeAndLockPages+118
fffff800`016a7b38 410fb601 ? ? ? ?movzx ? eax,byte ptr [r9]
MM_INTERNAL_CODE: ?5
DEFAULT_BUCKET_ID: ?WIN7_DRIVER_FAULT
BUGCHECK_STR: ?0x50
PROCESS_NAME: ?AdrvSvc
CURRENT_IRQL: ?0
TRAP_FRAME: ?fffff8800a8a4600 – (.trap 0xfffff8800a8a4600)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000000
rdx=0000000000000001 rsi=0000000000000000 rdi=0000000000000000
rip=fffff800016a7b38 rsp=fffff8800a8a4790 rbp=fffff8800a8a4ca0
?r8=fffffa803328e190 ?r9=ffffffff91ae00e0 r10=0000000000000000
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 ? ? ? ? nv up ei ng nz ac po nc
nt!MmProbeAndLockPages+0x118:
fffff800016a7b38 410fb601 ? ? ? ?movzx ? eax,byte ptr [r9] ds:ffffffff
91ae00e0=??
Resetting default scope
LAST_CONTROL_TRANSFER: ?from fffff800016328af to fffff8000168bfc0
STACK_TEXT: ?
fffff8800a8a4498 fffff800
016328af : 0000000000000050 ffffffff
91ae00e0 0000000000000000 fffff880
0a8a4600 : nt!KeBugCheckEx
fffff8800a8a44a0 fffff800
0168a0ee : 0000000000000000 ffffffff
91ae00e0 fffff88000000000 ffffffff
ffffffff : nt! ?? ::FNODOBFM::string'+0x437c1 fffff880
0a8a4600 fffff800016a7b38 : 00000000
2b4a7020 fffff8800a8a47a0 fffff880
0a8a0101 fffff8800a8a47d0 : nt!KiPageFault+0x16e fffff880
0a8a4790 fffff8800860671a : fffffa80
3328e160 fffff88008611b00 00000000
00000002 ffffffff91ae00e0 : nt!MmProbeAndLockPages+0x118 fffff880
0a8a48a0 fffff8800860884a : fffffa80
1acb6720 fffffa802f063a20 ffffffff
ffffffff 0000000000000000 : ADRV!IoctlHandler+0xf2 [f:\src\adrv\ioctl.c @ 772] fffff880
0a8a49b0 fffff88008608708 : 00000000
00000000 0000000000000001 fffffa80
2f063a20 0000000000000001 : ADRV!AdrvControl+0xae [f:\src\adrv\adrv.c @ 523] fffff880
0a8a49e0 fffff800019a2687 : fffffa80
2a2889f0 fffffa802a2889f0 fffffa80
2f063b38 fffffa802f063a20 : ADRV!AdrvDispatch+0x70 [f:\src\adrv\adrv.c @ 458] fffff880
0a8a4a10 fffff800019a2ee6 : fffff680
00000000 0000000000000000 00000000
00000000 0000000000000000 : nt!IopXxxControlFile+0x607 fffff880
0a8a4b40 fffff8000168b253 : 00000000
00093f01 0000000000000000 00000000
00000000 0000000000000000 : nt!NtDeviceIoControlFile+0x56 fffff880
0a8a4bb0 000000007749138a : 000007fe
fd5ba249 0000000022a3b9d8 00000000
22a3b800 0000000000000008 : nt!KiSystemServiceCopyEnd+0x13 00000000
2b4aeff8 000007fefd5ba249 : 00000000
22a3b9d8 0000000022a3b800 00000000
00000008 0000000073674f02 : ntdll!ZwDeviceIoControlFile+0xa 00000000
2b4af000 000000007733683f : 00000000
c352e018 00000005cd8000f0 00000000
2b4af0b0 000000018000b184 : KERNELBASE!DeviceIoControl+0x75 00000000
2b4af070 000000018000dca1 : 00000000
00000008 000000002b4af3c8 00000000
2b4af390 00000000000005f4 : kernel32!DeviceIoControlImplementation+0x7f 00000000
2b4af0c0 0000000000000000 : 00000000
00000000 0000000000000000 00000000
00000000 00000000`00000000 :?AdrvSvc!CallIoctl+0x431
The IoctHandler code where it blue-screens looks like this:
…
…
…
mdl = IoAllocateMdl(((InBuffer *)Irp->AssociatedIrp.SystemBuffer)->memoryBuffer, (ULONG)((InBuffer *)Irp->AssociatedIrp.SystemBuffer)->bufferSize, FALSE, FALSE, NULL);
if(mdl == NULL)
{
Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
}
_try
{
MmProbeAndLockPages(mdl, KernelMode, IoModifyAccess);
}
_except
(
pExceptionInfo = GetExceptionInformation(),
lclExceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode,
lclExceptionAddr = pExceptionInfo->ExceptionRecord->ExceptionAddress,
EXCEPTION_EXECUTE_HANDLER
)
{
…
Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
}
…
…
…
Declaration of the “InBuffer” structure looks like this:
typedef struct
{
UINT32 id;
UINT32 bufferSize;
UINT8* POINTER_32 memoryBuffer;
}InBuffer;
For now, I can not afford to make all the code changes required for eliminating the passing of the user mode buffer that is going on above for this IOCTL.
These are my questions:
-
Does the POINTER_32 declaration need to be removed, and the overall declaration changed to something like LONGLONG, because in case of the 64-bit app, this code is truncating the 64-bit pointer to the user mode app’s buffer, resulting in an invalid pointer being specified to IoAllocateMdl()?
-
Why does MmProbeAndLockPages() exhibit this behavior of succeeding most of the time, and blue-screening occasionally? Shouldn’t?MmProbeAndLockPages() just always fail, since an invalid address is specified in the mdl?
-
Even in those cases where the?64-bit driver is called by a 64-bit app, and does not blue-screen, shouldn’t the application be getting garbage results, because the driver did not perform processing on the intended buffer?