Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sending packets while Bluetooth tethering results in BSoD INVALID_MDL_RANGE #708

Closed
dmiller-nmap opened this issue Dec 22, 2023 · 4 comments
Labels
bug current Issues with current focus by the core Npcap dev team

Comments

@dmiller-nmap
Copy link
Contributor

Appears to not be limited to Npcap: found reports online of similar crashes in bthpan.sys due to WinPcap, SIEMENS S7 discovery driver, and others.

Surprisingly, the bugcheck text does not describe the crash conditions: VirtualAddress + Length is equal to SourceMDL->MappedSystemVa + SourceMDL->ByteCount, so the address range is within the range of the source MDL. The bthpan.sys driver appears to be trying to map the frame payload by skipping the 14 bytes of Ethernet frame header.

INVALID_MDL_RANGE (12e)
A driver has called the IoBuildPartialMdl() function and passed it an MDL
to map part of a source MDL, but the virtual address range specified is
outside the range in the source MDL.  This is a driver bug.  The source
and target MDLs, as well as the address range length to be mapped are the
arguments to the IoBuildPartialMdl() function, i.e.;
    IoBuildPartialMdl(
        IN PMDL SourceMdl,
        IN OUT PMDL TargetMdl,
        IN PVOID VirtualAddress,
        IN ULONG Length
        )
Arguments:
Arg1: ffffbd82c795d0a0
Arg2: ffffbd82b91c2fc0
Arg3: ffffab8158834d5e
Arg4: 000000000000002c

Debugging Details:
------------------

KEY_VALUES_STRING: 1

    Key  : Analysis.CPU.mSec
    Value: 5156

    Key  : Analysis.DebugAnalysisManager
    Value: Create

    Key  : Analysis.Elapsed.mSec
    Value: 13953

    Key  : Analysis.Init.CPU.mSec
    Value: 528968

    Key  : Analysis.Init.Elapsed.mSec
    Value: 337215851

    Key  : Analysis.Memory.CommitPeak.Mb
    Value: 4704

    Key  : WER.OS.Branch
    Value: ni_release_svc_prod3

    Key  : WER.OS.Timestamp
    Value: 2023-10-18T18:09:00Z

    Key  : WER.OS.Version
    Value: 10.0.22621.2506


DUMP_FILE_ATTRIBUTES: 0x1800

BUGCHECK_CODE:  12e

BUGCHECK_P1: ffffbd82c795d0a0

BUGCHECK_P2: ffffbd82b91c2fc0

BUGCHECK_P3: ffffab8158834d5e

BUGCHECK_P4: 2c

BLACKBOXBSD: 1 (!blackboxbsd)


BLACKBOXNTFS: 1 (!blackboxntfs)


BLACKBOXPNP: 1 (!blackboxpnp)


BLACKBOXWINLOGON: 1

PROCESS_NAME:  nmap.exe

STACK_TEXT:  
ffff9604`93ec69f8 fffff800`2c4d8212     : 00000000`0000012e ffffbd82`c795d0a0 ffffbd82`b91c2fc0 ffffab81`58834d5e : nt!KeBugCheckEx
ffff9604`93ec6a00 fffff800`0b541035     : ffffbd82`c795d0a0 ffffbd82`beaa3750 00000000`00000000 fffff800`0b5467b3 : nt!IoBuildPartialMdl+0x197592
ffff9604`93ec6a40 fffff800`0b54145c     : 00000000`00000000 ffffbd82`c8f50000 00000000`c000023e ffff9604`93ec6b70 : bthpan!BnepDataPacketConvertEthToBnep+0x321
ffff9604`93ec6aa0 fffff800`0b538cf1     : ffffbd82`af32a940 00000000`00000001 00000000`00000001 00000000`93ec6201 : bthpan!BnepDataSend+0x2b8
ffff9604`93ec6b20 fffff800`0b532eb9     : ffffbd82`ca632da0 fffff800`2d2c27d1 ffffbd82`af32a940 00000000`00000002 : bthpan!BthpanPacketSend+0x34d
ffff9604`93ec6c00 fffff800`2d2d851b     : ffffbd82`ad904a50 ffffbd82`ca632da0 00000000`00000000 ffff882c`f2a9e0e4 : bthpan!MpSendNetBufferLists+0x139
ffff9604`93ec6c40 fffff800`2e29822c     : 00000000`00000000 ffffbd82`b553d1a0 00000000`00000002 ffffbd82`ca286f02 : VerifierExt!XdvNdisMiniportSendNetBufferListsHandler_wrapper+0x11b
ffff9604`93ec6ca0 fffff800`2e263aee     : ffffbd82`ca632d01 ffffbd82`ca632da0 00000000`00000002 ffffbd82`ca286fb1 : ndis!ndisMSendNBLToMiniportInternal+0x3472c
ffff9604`93ec6d70 fffff800`2e284e02     : 00000000`00000000 ffff882c`f2a9e184 00000000`00000000 ffffbd82`ca632da0 : ndis!ndisMSendNBLToMiniport+0xe
ffff9604`93ec6db0 fffff800`2e26553a     : ffffbd82`ca640dc0 00000000`00000002 ffffbd82`ca678c60 ffffbd82`aebb80d0 : ndis!ndisInvokeNextSendHandler+0x42
ffff9604`93ec6e00 fffff800`2d2d63e6     : 00000000`00000000 ffffbd82`8b535a50 00000000`00000000 00000000`00000000 : ndis!NdisFSendNetBufferLists+0x12a
ffff9604`93ec6eb0 fffff800`2e31252d     : ffffbd82`b26c6e00 fffff800`2c75c060 ffffbd82`ad982e00 ffffbd82`ad982e00 : VerifierExt!XdvNdisFSendNetBufferLists_wrapper+0xd6
ffff9604`93ec6f10 fffff80f`ed2215e0     : ffffbd82`ca260f40 ffffbd82`ca632da0 fffff80f`ed226d20 ffffbd82`ca632da0 : ndis!ndisVerifierNdisFSendNetBufferLists+0x2d
ffff9604`93ec6f60 fffff800`2c348df7     : ffffbd82`ad982e00 ffffbd82`b26c6e00 00000000`00792d8a fffffe00`00003c98 : npcap!NPF_Write+0x500 [C:\Users\Nmap\Documents\Repos\npcap\packetWin7\npf\npf\Write.c @ 469] 
ffff9604`93ec6ff0 fffff800`2cadb22f     : ffffbd82`c795d0a0 00000000`00000001 ffffbd82`b3ee0080 ffffbd82`bfce70c0 : nt!IopfCallDriver+0x53
ffff9604`93ec7030 fffff800`2c4678c7     : ffffbd82`b26c6e00 ffff9604`93ec7111 00000000`00000000 00000000`00000000 : nt!IovCallDriver+0x5f
ffff9604`93ec7070 fffff800`2c75c060     : ffffbd82`b26c6e00 ffff9604`93ec7111 00000000`000cea88 ffffbd82`c833fc10 : nt!IofCallDriver+0x15fa27
ffff9604`93ec70b0 fffff800`2c743137     : ffffbd82`b26c6e00 ffff9604`93ec7290 ffff9604`93ec71d0 00000000`000cea88 : nt!IopSynchronousServiceTail+0x1d0
ffff9604`93ec7160 fffff800`2c742d83     : ffffbd82`c833fc10 00000000`0012019f ffffbd82`b26c6e00 00000000`00000000 : nt!IopWriteFile+0x267
ffff9604`93ec7280 fffff800`2c447be5     : 00000000`00000001 00000000`00000000 00000000`00000000 00000000`00000000 : nt!NtWriteFile+0x263
ffff9604`93ec7370 00000000`77011cf3     : 00000000`770119d3 00000023`7709674c 00007ff8`90920023 00000000`001ce8a4 : nt!KiSystemServiceCopyEnd+0x25
00000000`000cea38 00000000`770119d3     : 00000023`7709674c 00007ff8`90920023 00000000`001ce8a4 00000000`001ce6f8 : wow64cpu!CpupSyscallStub+0x13
00000000`000cea40 00000000`77011d75     : 00000000`001cfab4 00007ff8`9092cb78 00000000`00000000 00007ff8`9092ec97 : wow64cpu!ReadWriteFileFault+0x31
00000000`000ceaf0 00007ff8`9092ea8d     : 00000000`00331000 00000000`000cf530 00000000`00000000 00000000`000cf530 : wow64cpu!BTCpuSimulate+0xbb5
00000000`000ceb30 00007ff8`9092e18d     : 00000000`00000000 00000000`005a7120 00000000`00000000 00000000`00000000 : wow64!RunCpuSimulation+0xd
00000000`000ceb60 00007ff8`92bce427     : 00000000`009c0120 00007ff8`92c2b7f0 00000000`00330000 00007ff8`92c27c08 : wow64!Wow64LdrpInitialize+0x12d
00000000`000cee10 00007ff8`92bba184     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000001 : ntdll!LdrpInitializeProcess+0x174b
00000000`000cf1e0 00007ff8`92b63eb3     : 00000000`000cf530 00007ff8`92af0000 00000000`00330050 00000000`003337ee : ntdll!_LdrpInitialize+0x56298
00000000`000cf260 00007ff8`92b63dde     : 00000000`000cf530 00000000`00000000 00000000`000cf530 00000000`00000000 : ntdll!LdrpInitializeInternal+0x6b
00000000`000cf4e0 00000000`00000000     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!LdrInitializeThunk+0xe


SYMBOL_NAME:  bthpan!BnepDataPacketConvertEthToBnep+321

MODULE_NAME: bthpan

IMAGE_NAME:  bthpan.sys

STACK_COMMAND:  .thread ; .cxr ; kb

BUCKET_ID_FUNC_OFFSET:  321

FAILURE_BUCKET_ID:  0x12E_VRF_bthpan!BnepDataPacketConvertEthToBnep

OS_VERSION:  10.0.22621.2506

BUILDLAB_STR:  ni_release_svc_prod3

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

FAILURE_ID_HASH:  {451006ee-b0eb-6747-759f-763d29f53d27}

Followup:     MachineOwner
@dmiller-nmap dmiller-nmap added bug current Issues with current focus by the core Npcap dev team labels Dec 22, 2023
@dmiller-nmap
Copy link
Contributor Author

Remaining questions:

  1. Is there a special type of OOB/MediaSpecificInformation required for the NdisPhysicalMediumBluetooth?
  2. Can we trigger the same crash with similar parameters to IoBuildPartialMdl?
  3. Is there an alignment requirement for the frame payload or the VirtualAddress?

CC @jtippet if you have any insight here

@jtippet
Copy link

jtippet commented Dec 22, 2023

Thanks for the heads-up. I reviewed the bthpan.sys implementation and found a code bug, which I have reported internally to the Bluetooth team (internal-only reference: task.ms/16593126 ).

The issue is that bthpan is incorrectly using the mapped kernel VA in its call to IoBuildPartialMdl, and not the MDL's original VA. If the MDL is created in kernel mode (e.g. MmBuildMdlForNonPagedPool), these VAs are identical, so the mixup does not cause any symptoms. But in the case of npcap, it is mapping the MDL from usermode, so the VAs are different, and IoBuildPartialMdl blows up.

If you need to work around this, you can either:

  • Put the first 14 bytes (ethernet header) on a separate MDL from the rest of the packet, which will avoid sending bthpan down this path; or
  • Bounce the packet payload through a kernel buffer (e.g., ExAllocatePool + MmBuildMdlForNonPagedPool)

I'll address your specific questions, although they're potentially obsolete now.

  1. You do not need to do any fancy OOB dance for bthpan; this is not a bug in how npcap is building the packet.
  2. You could indeed trigger the same crash, if you pass a mapped kVA to IoBuildPartialMdl on an MDL that originated from a usermode buffer -- don't do that ;)
  3. There is no alignment requirement on any packet payload in NDIS6 (as much as some NIC drivers wished there were. But the newer NetAdapter model does allow NIC drivers to require alignment on transmits, and the OS handles that transparently for all the LWFs and protocols, so everyone's happy).

@dmiller-nmap
Copy link
Contributor Author

@jtippet Thanks so much for looking into this! We will try to work around the issue by using separate MDLs for Ethernet header and payload when the adapter has NdisPhysicalMediumBluetooth, since we can't count on users having a particular patchlevel. Is the correct approach when using IoBuildPartialMdl() to call MmGetMdlVirtualAddress() to obtain the MDL's original VA? Or should we use MmGetSystemAddressForMdlSafe() instead?

@jtippet
Copy link

jtippet commented Jan 2, 2024

MmGetMdlVirtualAddress gives you the original VA, which may be kVA or uVA, depending on where the MDL came from. MmGetSystemAddressForMdlSafe maps the MDL to kVA (if not already mapped) and gives you that kVA.

As a general rule, network drivers almost never deal in uVAs, so it's much more common to use MmGetSystemAddressForMdlSafe than MmGetMdlVirtualAddress in a network driver. (That habit likely led to this bug.) But here is an exception to that general rule: for the purposes of crafting parameters to IoBuildPartialMdl, use MmGetMdlVirtualAddress. And then forget about all those uVAs again -- it would be bad to actually dereference a uVA without setting up all the usual precautions ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug current Issues with current focus by the core Npcap dev team
Projects
None yet
Development

No branches or pull requests

2 participants