Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

Bluescreen on calling MmProbeAndLockPages()

OSR_Community_UserOSR_Community_User Member Posts: 110,217
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?

Comments

  • Scott_Noone_(OSR)Scott_Noone_(OSR) Administrator Posts: 3,096
    "Aspiring Programmer" <xxxxx@yahoo.com> 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" <xxxxx@yahoo.com> 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
    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

  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    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
    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_Noone_(OSR)Scott_Noone_(OSR) Administrator Posts: 3,096
    "Aspiring Programmer" <xxxxx@yahoo.com> 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" <xxxxx@yahoo.com> 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 <xxxxx@osr.com>
    To: Windows File Systems Devs Interest List <xxxxx@lists.osr.com>
    Sent: Tuesday, December 18, 2012 6:34 AM
    Subject: Re:[ntfsd] Bluescreen on calling MmProbeAndLockPages()


    "Aspiring Programmer" <xxxxx@yahoo.com> 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" <xxxxx@yahoo.com> 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
    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

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
Writing WDF Drivers 25 Feb 2019 OSR Seminar Space
Developing Minifilters 8 April 2019 OSR Seminar Space