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:
fffff800`016a7b38 410fb601 ? ? ? ?movzx ? eax,byte ptr [r9] ds:ffffffff`91ae00e0=??
Resetting default scope
LAST_CONTROL_TRANSFER: ?from fffff800016328af to fffff8000168bfc0
STACK_TEXT: ?
fffff880`0a8a4498 fffff800`016328af : 00000000`00000050 ffffffff`91ae00e0 00000000`00000000 fffff880`0a8a4600 : nt!KeBugCheckEx
fffff880`0a8a44a0 fffff800`0168a0ee : 00000000`00000000 ffffffff`91ae00e0 fffff880`00000000 ffffffff`ffffffff : nt! ?? ::FNODOBFM::`string'+0x437c1
fffff880`0a8a4600 fffff800`016a7b38 : 00000000`2b4a7020 fffff880`0a8a47a0 fffff880`0a8a0101 fffff880`0a8a47d0 : nt!KiPageFault+0x16e
fffff880`0a8a4790 fffff880`0860671a : fffffa80`3328e160 fffff880`08611b00 00000000`00000002 ffffffff`91ae00e0 : nt!MmProbeAndLockPages+0x118
fffff880`0a8a48a0 fffff880`0860884a : fffffa80`1acb6720 fffffa80`2f063a20 ffffffff`ffffffff 00000000`00000000 : ADRV!IoctlHandler+0xf2 [f:\src\adrv\ioctl.c @ 772]
fffff880`0a8a49b0 fffff880`08608708 : 00000000`00000000 00000000`00000001 fffffa80`2f063a20 00000000`00000001 : ADRV!AdrvControl+0xae [f:\src\adrv\adrv.c @ 523]
fffff880`0a8a49e0 fffff800`019a2687 : fffffa80`2a2889f0 fffffa80`2a2889f0 fffffa80`2f063b38 fffffa80`2f063a20 : ADRV!AdrvDispatch+0x70 [f:\src\adrv\adrv.c @ 458]
fffff880`0a8a4a10 fffff800`019a2ee6 : fffff680`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!IopXxxControlFile+0x607
fffff880`0a8a4b40 fffff800`0168b253 : 00000000`00093f01 00000000`00000000 00000000`00000000 00000000`00000000 : nt!NtDeviceIoControlFile+0x56
fffff880`0a8a4bb0 00000000`7749138a : 000007fe`fd5ba249 00000000`22a3b9d8 00000000`22a3b800 00000000`00000008 : nt!KiSystemServiceCopyEnd+0x13
00000000`2b4aeff8 000007fe`fd5ba249 : 00000000`22a3b9d8 00000000`22a3b800 00000000`00000008 00000000`73674f02 : ntdll!ZwDeviceIoControlFile+0xa
00000000`2b4af000 00000000`7733683f : 00000000`c352e018 00000005`cd8000f0 00000000`2b4af0b0 00000001`8000b184 : KERNELBASE!DeviceIoControl+0x75
00000000`2b4af070 00000001`8000dca1 : 00000000`00000008 00000000`2b4af3c8 00000000`2b4af390 00000000`000005f4 : kernel32!DeviceIoControlImplementation+0x7f
00000000`2b4af0c0 00000000`00000000 : 00000000`00000000 00000000`00000000 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?
0 ·
Comments
news:[email protected]
>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" <[email protected]> wrote in message
news:[email protected]
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:
fffff800`016a7b38 410fb601 movzx eax,byte ptr [r9]
ds:ffffffff`91ae00e0=??
Resetting default scope
LAST_CONTROL_TRANSFER: from fffff800016328af to fffff8000168bfc0
STACK_TEXT:
fffff880`0a8a4498 fffff800`016328af : 00000000`00000050 ffffffff`91ae00e0
00000000`00000000 fffff880`0a8a4600 : nt!KeBugCheckEx
fffff880`0a8a44a0 fffff800`0168a0ee : 00000000`00000000 ffffffff`91ae00e0
fffff880`00000000 ffffffff`ffffffff : nt! ?? ::FNODOBFM::`string'+0x437c1
fffff880`0a8a4600 fffff800`016a7b38 : 00000000`2b4a7020 fffff880`0a8a47a0
fffff880`0a8a0101 fffff880`0a8a47d0 : nt!KiPageFault+0x16e
fffff880`0a8a4790 fffff880`0860671a : fffffa80`3328e160 fffff880`08611b00
00000000`00000002 ffffffff`91ae00e0 : nt!MmProbeAndLockPages+0x118
fffff880`0a8a48a0 fffff880`0860884a : fffffa80`1acb6720 fffffa80`2f063a20
ffffffff`ffffffff 00000000`00000000 : ADRV!IoctlHandler+0xf2
[f:\src\adrv\ioctl.c @ 772]
fffff880`0a8a49b0 fffff880`08608708 : 00000000`00000000 00000000`00000001
fffffa80`2f063a20 00000000`00000001 : ADRV!AdrvControl+0xae
[f:\src\adrv\adrv.c @ 523]
fffff880`0a8a49e0 fffff800`019a2687 : fffffa80`2a2889f0 fffffa80`2a2889f0
fffffa80`2f063b38 fffffa80`2f063a20 : ADRV!AdrvDispatch+0x70
[f:\src\adrv\adrv.c @ 458]
fffff880`0a8a4a10 fffff800`019a2ee6 : fffff680`00000000 00000000`00000000
00000000`00000000 00000000`00000000 : nt!IopXxxControlFile+0x607
fffff880`0a8a4b40 fffff800`0168b253 : 00000000`00093f01 00000000`00000000
00000000`00000000 00000000`00000000 : nt!NtDeviceIoControlFile+0x56
fffff880`0a8a4bb0 00000000`7749138a : 000007fe`fd5ba249 00000000`22a3b9d8
00000000`22a3b800 00000000`00000008 : nt!KiSystemServiceCopyEnd+0x13
00000000`2b4aeff8 000007fe`fd5ba249 : 00000000`22a3b9d8 00000000`22a3b800
00000000`00000008 00000000`73674f02 : ntdll!ZwDeviceIoControlFile+0xa
00000000`2b4af000 00000000`7733683f : 00000000`c352e018 00000005`cd8000f0
00000000`2b4af0b0 00000001`8000b184 : KERNELBASE!DeviceIoControl+0x75
00000000`2b4af070 00000001`8000dca1 : 00000000`00000008 00000000`2b4af3c8
00000000`2b4af390 00000000`000005f4 :
kernel32!DeviceIoControlImplementation+0x7f
00000000`2b4af0c0 00000000`00000000 : 00000000`00000000 00000000`00000000
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?
-scott
OSR
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:[email protected]
> 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:[email protected]
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:
fffff800`016a7b38 410fb601? ? ? ? movzx? eax,byte ptr [r9] ds:ffffffff`91ae00e0=??
Resetting default scope
LAST_CONTROL_TRANSFER:? from fffff800016328af to fffff8000168bfc0
STACK_TEXT:
fffff880`0a8a4498 fffff800`016328af : 00000000`00000050 ffffffff`91ae00e0 00000000`00000000 fffff880`0a8a4600 : nt!KeBugCheckEx
fffff880`0a8a44a0 fffff800`0168a0ee : 00000000`00000000 ffffffff`91ae00e0 fffff880`00000000 ffffffff`ffffffff : nt! ?? ::FNODOBFM::`string'+0x437c1
fffff880`0a8a4600 fffff800`016a7b38 : 00000000`2b4a7020 fffff880`0a8a47a0 fffff880`0a8a0101 fffff880`0a8a47d0 : nt!KiPageFault+0x16e
fffff880`0a8a4790 fffff880`0860671a : fffffa80`3328e160 fffff880`08611b00 00000000`00000002 ffffffff`91ae00e0 : nt!MmProbeAndLockPages+0x118
fffff880`0a8a48a0 fffff880`0860884a : fffffa80`1acb6720 fffffa80`2f063a20 ffffffff`ffffffff 00000000`00000000 : ADRV!IoctlHandler+0xf2 [f:\src\adrv\ioctl.c @ 772]
fffff880`0a8a49b0 fffff880`08608708 : 00000000`00000000 00000000`00000001 fffffa80`2f063a20 00000000`00000001 : ADRV!AdrvControl+0xae [f:\src\adrv\adrv.c @ 523]
fffff880`0a8a49e0 fffff800`019a2687 : fffffa80`2a2889f0 fffffa80`2a2889f0 fffffa80`2f063b38 fffffa80`2f063a20 : ADRV!AdrvDispatch+0x70 [f:\src\adrv\adrv.c @ 458]
fffff880`0a8a4a10 fffff800`019a2ee6 : fffff680`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!IopXxxControlFile+0x607
fffff880`0a8a4b40 fffff800`0168b253 : 00000000`00093f01 00000000`00000000 00000000`00000000 00000000`00000000 : nt!NtDeviceIoControlFile+0x56
fffff880`0a8a4bb0 00000000`7749138a : 000007fe`fd5ba249 00000000`22a3b9d8 00000000`22a3b800 00000000`00000008 : nt!KiSystemServiceCopyEnd+0x13
00000000`2b4aeff8 000007fe`fd5ba249 : 00000000`22a3b9d8 00000000`22a3b800 00000000`00000008 00000000`73674f02 : ntdll!ZwDeviceIoControlFile+0xa
00000000`2b4af000 00000000`7733683f : 00000000`c352e018 00000005`cd8000f0 00000000`2b4af0b0 00000001`8000b184 : KERNELBASE!DeviceIoControl+0x75
00000000`2b4af070 00000001`8000dca1 : 00000000`00000008 00000000`2b4af3c8 00000000`2b4af390 00000000`000005f4 : kernel32!DeviceIoControlImplementation+0x7f
00000000`2b4af0c0 00000000`00000000 : 00000000`00000000 00000000`00000000 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?
---
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
news:[email protected]
>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" <[email protected]> wrote in message
news:[email protected]
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 <[email protected]>
To: Windows File Systems Devs Interest List <[email protected]>
Sent: Tuesday, December 18, 2012 6:34 AM
Subject: Re:[ntfsd] Bluescreen on calling MmProbeAndLockPages()
"Aspiring Programmer" <[email protected]> wrote in message
news:[email protected]
> 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" <[email protected]> wrote in message
news:[email protected]
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:
fffff800`016a7b38 410fb601 movzx eax,byte ptr [r9]
ds:ffffffff`91ae00e0=??
Resetting default scope
LAST_CONTROL_TRANSFER: from fffff800016328af to fffff8000168bfc0
STACK_TEXT:
fffff880`0a8a4498 fffff800`016328af : 00000000`00000050 ffffffff`91ae00e0
00000000`00000000 fffff880`0a8a4600 : nt!KeBugCheckEx
fffff880`0a8a44a0 fffff800`0168a0ee : 00000000`00000000 ffffffff`91ae00e0
fffff880`00000000 ffffffff`ffffffff : nt! ?? ::FNODOBFM::`string'+0x437c1
fffff880`0a8a4600 fffff800`016a7b38 : 00000000`2b4a7020 fffff880`0a8a47a0
fffff880`0a8a0101 fffff880`0a8a47d0 : nt!KiPageFault+0x16e
fffff880`0a8a4790 fffff880`0860671a : fffffa80`3328e160 fffff880`08611b00
00000000`00000002 ffffffff`91ae00e0 : nt!MmProbeAndLockPages+0x118
fffff880`0a8a48a0 fffff880`0860884a : fffffa80`1acb6720 fffffa80`2f063a20
ffffffff`ffffffff 00000000`00000000 : ADRV!IoctlHandler+0xf2
[f:\src\adrv\ioctl.c @ 772]
fffff880`0a8a49b0 fffff880`08608708 : 00000000`00000000 00000000`00000001
fffffa80`2f063a20 00000000`00000001 : ADRV!AdrvControl+0xae
[f:\src\adrv\adrv.c @ 523]
fffff880`0a8a49e0 fffff800`019a2687 : fffffa80`2a2889f0 fffffa80`2a2889f0
fffffa80`2f063b38 fffffa80`2f063a20 : ADRV!AdrvDispatch+0x70
[f:\src\adrv\adrv.c @ 458]
fffff880`0a8a4a10 fffff800`019a2ee6 : fffff680`00000000 00000000`00000000
00000000`00000000 00000000`00000000 : nt!IopXxxControlFile+0x607
fffff880`0a8a4b40 fffff800`0168b253 : 00000000`00093f01 00000000`00000000
00000000`00000000 00000000`00000000 : nt!NtDeviceIoControlFile+0x56
fffff880`0a8a4bb0 00000000`7749138a : 000007fe`fd5ba249 00000000`22a3b9d8
00000000`22a3b800 00000000`00000008 : nt!KiSystemServiceCopyEnd+0x13
00000000`2b4aeff8 000007fe`fd5ba249 : 00000000`22a3b9d8 00000000`22a3b800
00000000`00000008 00000000`73674f02 : ntdll!ZwDeviceIoControlFile+0xa
00000000`2b4af000 00000000`7733683f : 00000000`c352e018 00000005`cd8000f0
00000000`2b4af0b0 00000001`8000b184 : KERNELBASE!DeviceIoControl+0x75
00000000`2b4af070 00000001`8000dca1 : 00000000`00000008 00000000`2b4af3c8
00000000`2b4af390 00000000`000005f4 :
kernel32!DeviceIoControlImplementation+0x7f
00000000`2b4af0c0 00000000`00000000 : 00000000`00000000 00000000`00000000
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?
---
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
-scott
OSR