Bluescreen on calling MmProbeAndLockPages()

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:ffffffff91ae00e0=??
Resetting default scope

LAST_CONTROL_TRANSFER: ?from fffff800016328af to fffff8000168bfc0

STACK_TEXT: ?
fffff8800a8a4498 fffff800016328af : 0000000000000050 ffffffff91ae00e0 0000000000000000 fffff8800a8a4600 : nt!KeBugCheckEx
fffff8800a8a44a0 fffff8000168a0ee : 0000000000000000 ffffffff91ae00e0 fffff88000000000 ffffffffffffffff : nt! ?? ::FNODOBFM::string'+0x437c1 fffff8800a8a4600 fffff800016a7b38 : 000000002b4a7020 fffff8800a8a47a0 fffff8800a8a0101 fffff8800a8a47d0 : nt!KiPageFault+0x16e fffff8800a8a4790 fffff8800860671a : fffffa803328e160 fffff88008611b00 0000000000000002 ffffffff91ae00e0 : nt!MmProbeAndLockPages+0x118 fffff8800a8a48a0 fffff8800860884a : fffffa801acb6720 fffffa802f063a20 ffffffffffffffff 0000000000000000 : ADRV!IoctlHandler+0xf2 [f:\src\adrv\ioctl.c @ 772] fffff8800a8a49b0 fffff88008608708 : 0000000000000000 0000000000000001 fffffa802f063a20 0000000000000001 : ADRV!AdrvControl+0xae [f:\src\adrv\adrv.c @ 523] fffff8800a8a49e0 fffff800019a2687 : fffffa802a2889f0 fffffa802a2889f0 fffffa802f063b38 fffffa802f063a20 : ADRV!AdrvDispatch+0x70 [f:\src\adrv\adrv.c @ 458] fffff8800a8a4a10 fffff800019a2ee6 : fffff68000000000 0000000000000000 0000000000000000 0000000000000000 : nt!IopXxxControlFile+0x607 fffff8800a8a4b40 fffff8000168b253 : 0000000000093f01 0000000000000000 0000000000000000 0000000000000000 : nt!NtDeviceIoControlFile+0x56 fffff8800a8a4bb0 000000007749138a : 000007fefd5ba249 0000000022a3b9d8 0000000022a3b800 0000000000000008 : nt!KiSystemServiceCopyEnd+0x13 000000002b4aeff8 000007fefd5ba249 : 0000000022a3b9d8 0000000022a3b800 0000000000000008 0000000073674f02 : ntdll!ZwDeviceIoControlFile+0xa 000000002b4af000 000000007733683f : 00000000c352e018 00000005cd8000f0 000000002b4af0b0 000000018000b184 : KERNELBASE!DeviceIoControl+0x75 000000002b4af070 000000018000dca1 : 0000000000000008 000000002b4af3c8 000000002b4af390 00000000000005f4 : kernel32!DeviceIoControlImplementation+0x7f 000000002b4af0c0 0000000000000000 : 0000000000000000 0000000000000000 0000000000000000 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?

“Aspiring Programmer” wrote in message
news:xxxxx@ntfsd…
>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()?

Typically what you do in this case is have two structures: one for 32-bit
callers and one for 64-bit:

http://msdn.microsoft.com/en-us/library/windows/hardware/ff564612(v=vs.85).aspx

In your case, because you’re forcing the 64-bit pointer to be 32-bit you’re
basically passing garbage for the upper half of your pointer.

>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?

Have you called ProbeForWrite on the buffer from the user? If not, you’re
not properly validating the input from the user and that can lead to system
crashes.

Also, what buffering method are you using for your IOCTL? You may have other
bugs in your code if it’s METHOD_NEITHER or METHOD_XXX_DIRECT.

-scott
OSR

“Aspiring Programmer” wrote in message
news:xxxxx@ntfsd…
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
fffff800016a7b38 410fb601 movzx eax,byte ptr [r9]<br><br>MM_INTERNAL_CODE: 5<br><br>DEFAULT_BUCKET_ID: WIN7_DRIVER_FAULT<br><br>BUGCHECK_STR: 0x50<br><br>PROCESS_NAME: AdrvSvc<br><br>CURRENT_IRQL: 0<br><br>TRAP_FRAME: fffff8800a8a4600 -- (.trap 0xfffff8800a8a4600)<br>NOTE: The trap frame does not contain all registers.<br>Some register values may be zeroed or incorrect.<br>rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000000<br>rdx=0000000000000001 rsi=0000000000000000 rdi=0000000000000000<br>rip=fffff800016a7b38 rsp=fffff8800a8a4790 rbp=fffff8800a8a4ca0<br>r8=fffffa803328e190 r9=ffffffff91ae00e0 r10=0000000000000000<br>r11=0000000000000000 r12=0000000000000000 r13=0000000000000000<br>r14=0000000000000000 r15=0000000000000000<br>iopl=0 nv up ei ng nz ac po nc<br>nt!MmProbeAndLockPages+0x118:<br>fffff800016a7b38 410fb601 movzx eax,byte ptr [r9]
ds:ffffffff91ae00e0=??<br>Resetting default scope<br><br>LAST_CONTROL_TRANSFER: from fffff800016328af to fffff8000168bfc0<br><br>STACK_TEXT:<br>fffff8800a8a4498 fffff800016328af : 0000000000000050 ffffffff91ae00e0 <br>0000000000000000 fffff8800a8a4600 : nt!KeBugCheckEx<br>fffff8800a8a44a0 fffff8000168a0ee : 0000000000000000 ffffffff91ae00e0 <br>fffff88000000000 ffffffffffffffff : nt! ?? ::FNODOBFM::string’+0x437c1
fffff8800a8a4600 fffff800016a7b38 : 000000002b4a7020 fffff8800a8a47a0
fffff8800a8a0101 fffff8800a8a47d0 : nt!KiPageFault+0x16e
fffff8800a8a4790 fffff8800860671a : fffffa803328e160 fffff88008611b00
0000000000000002 ffffffff91ae00e0 : nt!MmProbeAndLockPages+0x118
fffff8800a8a48a0 fffff8800860884a : fffffa801acb6720 fffffa802f063a20
ffffffffffffffff 0000000000000000 : ADRV!IoctlHandler+0xf2
[f:\src\adrv\ioctl.c @ 772]
fffff8800a8a49b0 fffff88008608708 : 0000000000000000 0000000000000001
fffffa802f063a20 0000000000000001 : ADRV!AdrvControl+0xae
[f:\src\adrv\adrv.c @ 523]
fffff8800a8a49e0 fffff800019a2687 : fffffa802a2889f0 fffffa802a2889f0
fffffa802f063b38 fffffa802f063a20 : ADRV!AdrvDispatch+0x70
[f:\src\adrv\adrv.c @ 458]
fffff8800a8a4a10 fffff800019a2ee6 : fffff68000000000 0000000000000000
0000000000000000 0000000000000000 : nt!IopXxxControlFile+0x607
fffff8800a8a4b40 fffff8000168b253 : 0000000000093f01 0000000000000000
0000000000000000 0000000000000000 : nt!NtDeviceIoControlFile+0x56
fffff8800a8a4bb0 000000007749138a : 000007fefd5ba249 0000000022a3b9d8
0000000022a3b800 0000000000000008 : nt!KiSystemServiceCopyEnd+0x13
000000002b4aeff8 000007fefd5ba249 : 0000000022a3b9d8 0000000022a3b800
0000000000000008 0000000073674f02 : ntdll!ZwDeviceIoControlFile+0xa
000000002b4af000 000000007733683f : 00000000c352e018 00000005cd8000f0
000000002b4af0b0 000000018000b184 : KERNELBASE!DeviceIoControl+0x75
000000002b4af070 000000018000dca1 : 0000000000000008 000000002b4af3c8
000000002b4af390 00000000000005f4 :
kernel32!DeviceIoControlImplementation+0x7f
000000002b4af0c0 0000000000000000 : 0000000000000000 0000000000000000
0000000000000000 0000000000000000 : 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?

Thank you, Scott. The IOCTL uses METHOD_BUFFERED, so that pat of the code looks all right.

Should I really need to call ProbeForWrite() before calling MmProbeAndLockPages() ?

I see the pointer truncation bug, but was a little surprised that MmProbeAndLockPages() randomly blue-screened on being passed a bad pointer in the mdl.

Isn’t it supposed to fail?


From: Scott Noone
To: Windows File Systems Devs Interest List
Sent: Tuesday, December 18, 2012 6:34 AM
Subject: Re:[ntfsd] Bluescreen on calling MmProbeAndLockPages()

“Aspiring Programmer” wrote in message news:xxxxx@ntfsd…
> 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()?

Typically what you do in this case is have two structures: one for 32-bit callers and one for 64-bit:

http://msdn.microsoft.com/en-us/library/windows/hardware/ff564612(v=vs.85).aspx

In your case, because you’re forcing the 64-bit pointer to be 32-bit you’re basically passing garbage for the upper half of your pointer.

> 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?

Have you called ProbeForWrite on the buffer from the user? If not, you’re not properly validating the input from the user and that can lead to system crashes.

Also, what buffering method are you using for your IOCTL? You may have other bugs in your code if it’s METHOD_NEITHER or METHOD_XXX_DIRECT.

-scott
OSR

“Aspiring Programmer” wrote in message news:xxxxx@ntfsd…
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
fffff800016a7b38 410fb601? ? ? ? movzx? eax,byte ptr [r9]<br><br>MM_INTERNAL_CODE:? 5<br><br>DEFAULT_BUCKET_ID:? WIN7_DRIVER_FAULT<br><br>BUGCHECK_STR:? 0x50<br><br>PROCESS_NAME:? AdrvSvc<br><br>CURRENT_IRQL:? 0<br><br>TRAP_FRAME:? fffff8800a8a4600 -- (.trap 0xfffff8800a8a4600)<br>NOTE: The trap frame does not contain all registers.<br>Some register values may be zeroed or incorrect.<br>rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000000<br>rdx=0000000000000001 rsi=0000000000000000 rdi=0000000000000000<br>rip=fffff800016a7b38 rsp=fffff8800a8a4790 rbp=fffff8800a8a4ca0<br>r8=fffffa803328e190? r9=ffffffff91ae00e0 r10=0000000000000000<br>r11=0000000000000000 r12=0000000000000000 r13=0000000000000000<br>r14=0000000000000000 r15=0000000000000000<br>iopl=0? ? ? ? nv up ei ng nz ac po nc<br>nt!MmProbeAndLockPages+0x118:<br>fffff800016a7b38 410fb601? ? ? ? movzx? eax,byte ptr [r9] ds:ffffffff91ae00e0=??<br>Resetting default scope<br><br>LAST_CONTROL_TRANSFER:? from fffff800016328af to fffff8000168bfc0<br><br>STACK_TEXT:<br>fffff8800a8a4498 fffff800016328af : 0000000000000050 ffffffff91ae00e0 0000000000000000 fffff8800a8a4600 : nt!KeBugCheckEx<br>fffff8800a8a44a0 fffff8000168a0ee : 0000000000000000 ffffffff91ae00e0 fffff88000000000 ffffffffffffffff : nt! ?? ::FNODOBFM::string’+0x437c1
fffff8800a8a4600 fffff800016a7b38 : 000000002b4a7020 fffff8800a8a47a0 fffff8800a8a0101 fffff8800a8a47d0 : nt!KiPageFault+0x16e
fffff8800a8a4790 fffff8800860671a : fffffa803328e160 fffff88008611b00 0000000000000002 ffffffff91ae00e0 : nt!MmProbeAndLockPages+0x118
fffff8800a8a48a0 fffff8800860884a : fffffa801acb6720 fffffa802f063a20 ffffffffffffffff 0000000000000000 : ADRV!IoctlHandler+0xf2 [f:\src\adrv\ioctl.c @ 772]
fffff8800a8a49b0 fffff88008608708 : 0000000000000000 0000000000000001 fffffa802f063a20 0000000000000001 : ADRV!AdrvControl+0xae [f:\src\adrv\adrv.c @ 523]
fffff8800a8a49e0 fffff800019a2687 : fffffa802a2889f0 fffffa802a2889f0 fffffa802f063b38 fffffa802f063a20 : ADRV!AdrvDispatch+0x70 [f:\src\adrv\adrv.c @ 458]
fffff8800a8a4a10 fffff800019a2ee6 : fffff68000000000 0000000000000000 0000000000000000 0000000000000000 : nt!IopXxxControlFile+0x607
fffff8800a8a4b40 fffff8000168b253 : 0000000000093f01 0000000000000000 0000000000000000 0000000000000000 : nt!NtDeviceIoControlFile+0x56
fffff8800a8a4bb0 000000007749138a : 000007fefd5ba249 0000000022a3b9d8 0000000022a3b800 0000000000000008 : nt!KiSystemServiceCopyEnd+0x13
000000002b4aeff8 000007fefd5ba249 : 0000000022a3b9d8 0000000022a3b800 0000000000000008 0000000073674f02 : ntdll!ZwDeviceIoControlFile+0xa
000000002b4af000 000000007733683f : 00000000c352e018 00000005cd8000f0 000000002b4af0b0 000000018000b184 : KERNELBASE!DeviceIoControl+0x75
000000002b4af070 000000018000dca1 : 0000000000000008 000000002b4af3c8 000000002b4af390 00000000000005f4 : kernel32!DeviceIoControlImplementation+0x7f
000000002b4af0c0 0000000000000000 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : 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?


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars visit: http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

“Aspiring Programmer” wrote in message
news:xxxxx@ntfsd…
>I see the pointer truncation bug, but was a little surprised that
>MmProbeAndLockPages() randomly blue-screened on being >passed a bad pointer
>in the mdl.

Invalid user buffers raise exceptions when they are dereferenced, invalid
kernel buffers crash the machine on dereference.
If you call MmProbeAndLockPages with an AccessMode of KernelMode, the O/S is
going to assume that the buffer supplied is valid in its processing. If the
user then supplies a bogus kernel address as their buffer, you may end up
crashing the machine.

The better idea would be to pass Irp->RequestorMode as the second parameter
to MmProbeAndLockPages. In this case, if the requestor is UserMode and the
buffer is a kernel address the API will immediately raise an exception
instead of potentially crashing. Calling ProbeForWrite yourself would
basically give you the same effect (it also checks to make sure the buffer
supplied is a user address), which is why I asked if you were making this
call earlier as it would point to this being a different type of bug.

-scott
OSR

“Aspiring Programmer” wrote in message
news:xxxxx@ntfsd…
Thank you, Scott. The IOCTL uses METHOD_BUFFERED, so that pat of the code
looks all right.

Should I really need to call ProbeForWrite() before calling
MmProbeAndLockPages() ?

I see the pointer truncation bug, but was a little surprised that
MmProbeAndLockPages() randomly blue-screened on being passed a bad pointer
in the mdl.

Isn’t it supposed to fail?

From: Scott Noone
To: Windows File Systems Devs Interest List
Sent: Tuesday, December 18, 2012 6:34 AM
Subject: Re:[ntfsd] Bluescreen on calling MmProbeAndLockPages()

“Aspiring Programmer” wrote in message
news:xxxxx@ntfsd…
> 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()?

Typically what you do in this case is have two structures: one for 32-bit
callers and one for 64-bit:

http://msdn.microsoft.com/en-us/library/windows/hardware/ff564612(v=vs.85).aspx

In your case, because you’re forcing the 64-bit pointer to be 32-bit you’re
basically passing garbage for the upper half of your pointer.

> 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?

Have you called ProbeForWrite on the buffer from the user? If not, you’re
not properly validating the input from the user and that can lead to system
crashes.

Also, what buffering method are you using for your IOCTL? You may have other
bugs in your code if it’s METHOD_NEITHER or METHOD_XXX_DIRECT.

-scott
OSR

“Aspiring Programmer” wrote in message
news:xxxxx@ntfsd…
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
fffff800016a7b38 410fb601 movzx eax,byte ptr [r9]<br><br>MM_INTERNAL_CODE: 5<br><br>DEFAULT_BUCKET_ID: WIN7_DRIVER_FAULT<br><br>BUGCHECK_STR: 0x50<br><br>PROCESS_NAME: AdrvSvc<br><br>CURRENT_IRQL: 0<br><br>TRAP_FRAME: fffff8800a8a4600 -- (.trap 0xfffff8800a8a4600)<br>NOTE: The trap frame does not contain all registers.<br>Some register values may be zeroed or incorrect.<br>rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000000<br>rdx=0000000000000001 rsi=0000000000000000 rdi=0000000000000000<br>rip=fffff800016a7b38 rsp=fffff8800a8a4790 rbp=fffff8800a8a4ca0<br>r8=fffffa803328e190 r9=ffffffff91ae00e0 r10=0000000000000000<br>r11=0000000000000000 r12=0000000000000000 r13=0000000000000000<br>r14=0000000000000000 r15=0000000000000000<br>iopl=0 nv up ei ng nz ac po nc<br>nt!MmProbeAndLockPages+0x118:<br>fffff800016a7b38 410fb601 movzx eax,byte ptr [r9]
ds:ffffffff91ae00e0=??<br>Resetting default scope<br><br>LAST_CONTROL_TRANSFER: from fffff800016328af to fffff8000168bfc0<br><br>STACK_TEXT:<br>fffff8800a8a4498 fffff800016328af : 0000000000000050 ffffffff91ae00e0 <br>0000000000000000 fffff8800a8a4600 : nt!KeBugCheckEx<br>fffff8800a8a44a0 fffff8000168a0ee : 0000000000000000 ffffffff91ae00e0 <br>fffff88000000000 ffffffffffffffff : nt! ?? ::FNODOBFM::string’+0x437c1
fffff8800a8a4600 fffff800016a7b38 : 000000002b4a7020 fffff8800a8a47a0
fffff8800a8a0101 fffff8800a8a47d0 : nt!KiPageFault+0x16e
fffff8800a8a4790 fffff8800860671a : fffffa803328e160 fffff88008611b00
0000000000000002 ffffffff91ae00e0 : nt!MmProbeAndLockPages+0x118
fffff8800a8a48a0 fffff8800860884a : fffffa801acb6720 fffffa802f063a20
ffffffffffffffff 0000000000000000 : ADRV!IoctlHandler+0xf2
[f:\src\adrv\ioctl.c @ 772]
fffff8800a8a49b0 fffff88008608708 : 0000000000000000 0000000000000001
fffffa802f063a20 0000000000000001 : ADRV!AdrvControl+0xae
[f:\src\adrv\adrv.c @ 523]
fffff8800a8a49e0 fffff800019a2687 : fffffa802a2889f0 fffffa802a2889f0
fffffa802f063b38 fffffa802f063a20 : ADRV!AdrvDispatch+0x70
[f:\src\adrv\adrv.c @ 458]
fffff8800a8a4a10 fffff800019a2ee6 : fffff68000000000 0000000000000000
0000000000000000 0000000000000000 : nt!IopXxxControlFile+0x607
fffff8800a8a4b40 fffff8000168b253 : 0000000000093f01 0000000000000000
0000000000000000 0000000000000000 : nt!NtDeviceIoControlFile+0x56
fffff8800a8a4bb0 000000007749138a : 000007fefd5ba249 0000000022a3b9d8
0000000022a3b800 0000000000000008 : nt!KiSystemServiceCopyEnd+0x13
000000002b4aeff8 000007fefd5ba249 : 0000000022a3b9d8 0000000022a3b800
0000000000000008 0000000073674f02 : ntdll!ZwDeviceIoControlFile+0xa
000000002b4af000 000000007733683f : 00000000c352e018 00000005cd8000f0
000000002b4af0b0 000000018000b184 : KERNELBASE!DeviceIoControl+0x75
000000002b4af070 000000018000dca1 : 0000000000000008 000000002b4af3c8
000000002b4af390 00000000000005f4 :
kernel32!DeviceIoControlImplementation+0x7f
000000002b4af0c0 0000000000000000 : 0000000000000000 0000000000000000
0000000000000000 0000000000000000 : 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?


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer