TDI filter NO_MORE_IRP_STACK_LOCATIONS bluescreen with a twist

Hi all,

I’m getting a NO_MORE_IRP_STACK_LOCATIONS BSoD on Windows 8.1 x64 in my TDI filter driver.

I’ve read enough past threads to know there historically have been problems in the networking stack with NetBT and friends allocating a set number of stack locations from a registry value, and the answer is to either create a new IRP or skip the IRP before calling the next in the chain. However, I’ve come across something I believe is unusual.

My driver already skipped this IRP before passing it onto the next driver. I am absolutely sure the stack location was not modified in any other way by my code. This implies CurrentLocation was already 0 at the time I received it! That means NetBT (the TDI client issuing the IRP in my case) should have gotten the bluescreen, not me. I checked the disassembly of netbt!NbtWorkItemPostClientIrpToProvider - it does indeed call IofCallDriver, not anything hacky that could bypass this stack location check.
That being said, I’m also confused as to why IofCallDriver doesn’t show up in the stack trace in between netbt!NbtWorkItemPostClientIrpToProvider and myfilter!dispatch_request.

3: kd> k

Child-SP RetAddr Call Site

00 ffffd000dcf069a8 fffff8016b35d892 nt!KeBugCheckEx
01 ffffd000dcf069b0 fffff8016b393b6b nt!KiBugCheck3+0x12
02 ffffd000dcf069e0 fffff800c52a90b4 nt! ?? ::FNODOBFM::string'+0x25dab ;this is IofCallDriver 03 ffffd000dcf06a10 fffff800c52a5b60 myfilter!tcp_TdiReceive+0x22c 04 ffffd000dcf06a50 fffff800c52afd48 myfilter!dispatch_tcp+0x140 05 ffffd000dcf06a80 fffff800c432e764 myfilter!dispatch_request+0x2c 06 ffffd000dcf06ab0 fffff8016b2f4228 netbt!NbtWorkItemPostClientIrpToProvider+0x6c 07 ffffd000dcf06ae0 fffff8016b29e4bf nt!IopProcessWorkItem+0x80 08 ffffd000dcf06b50 fffff8016b30b554 nt!ExpWorkerThread+0x69f 09 ffffd000dcf06c00 fffff8016b363ec6 nt!PspSystemThreadStartup+0x58 0a ffffd000dcf06c60 00000000`00000000 nt!KiStartSystemThread+0x16

3: kd> !irp ffffe00208e69d00 1
Irp is active with 3 stacks 0 is current (= 0xffffe002088b2320)
Mdl=ffffe002087b8cd0: No System Buffer: Thread 00000000: Irp stack trace. Pending has been returned
Flags = 00000000
ThreadListEntry.Flink = ffffe00208e69d20
ThreadListEntry.Blink = ffffe00208e69d20
IoStatus.Status = c0000016
IoStatus.Information = 000005b4
RequestorMode = 00000000
Cancel = 00
CancelIrql = 0
ApcEnvironment = 01
UserIosb = 00000000
UserEvent = 00000000
Overlay.AsynchronousParameters.UserApcRoutine = 00000000
Overlay.AsynchronousParameters.UserApcContext = 00000000
Overlay.AllocationSize = 00000000 - 00000000
CancelRoutine = 00000000
UserBuffer = 00000000
&Tail.Overlay.DeviceQueueEntry = ffffe00208e69d78
Tail.Overlay.Thread = 00000000
Tail.Overlay.AuxiliaryBuffer = 00000000
Tail.Overlay.ListEntry.Flink = 00000000
Tail.Overlay.ListEntry.Blink = ffffe002070c11f0
Tail.Overlay.CurrentStackLocation = ffffe002088b2320
Tail.Overlay.OriginalFileObject = 00000000
Tail.Apc = 07e58d80
Tail.CompletionKey = ffffe00207e58d80
cmd flg cl Device File Completion-Context
[IRP_MJ_INTERNAL_DEVICE_CONTROL(f), N/A(8)]
0 e0 ffffe002070c11f0 ffffe002088b2320 fffff800c4319690-ffffe002089c1720 Success Error Cancel
\Driver\myfilter netbt!NbtClientIrpCompletion
Args: 20000028b8 00000000 00000000 00000000
[IRP_MJ_INTERNAL_DEVICE_CONTROL(f), N/A(8)]
0 e0 ffffe00206480b20 ffffe001ff687dd0 fffff800c4a720b0-ffffe0020780bdf0 Success Error Cancel
\Driver\NetBT mrxsmb!RxTdiReceiveCompletion
Args: 00002e6c 00000000 00000000 00000000
[N/A(0), N/A(0)]
0 0 00000000 00000000 00000000-ffffe002086af010

Args: fffff800c3f1c180 fffff800c3f1c180 ffffe00208e69d00 20b46af0

I’m not sure about the issue you’re seeing, but:

Tail Call Optimization. Disassemble IofCallDriver and you’ll see that it
ends in a JMP, not a RET. For example:

mov r8,qword ptr [rcx+8]
movzx eax,r9b
add rsp,38h
jmp qword ptr [r8+rax*8+70h]

This means the return address is not on the stack (you’re not going to
return to it) and it won’t show up in the k output.

-scott
OSR
@OSRDrivers

wrote in message news:xxxxx@ntdev…

Hi all,

I’m getting a NO_MORE_IRP_STACK_LOCATIONS BSoD on Windows 8.1 x64 in my TDI
filter driver.

I’ve read enough past threads to know there historically have been problems
in the networking stack with NetBT and friends allocating a set number of
stack locations from a registry value, and the answer is to either create a
new IRP or skip the IRP before calling the next in the chain. However, I’ve
come across something I believe is unusual.

My driver already skipped this IRP before passing it onto the next driver.
I am absolutely sure the stack location was not modified in any other way by
my code. This implies CurrentLocation was already 0 at the time I received
it! That means NetBT (the TDI client issuing the IRP in my case) should
have gotten the bluescreen, not me. I checked the disassembly of
netbt!NbtWorkItemPostClientIrpToProvider - it does indeed call
IofCallDriver, not anything hacky that could bypass this stack location
check.
That being said, I’m also confused as to why IofCallDriver doesn’t show up
in the stack trace in between netbt!NbtWorkItemPostClientIrpToProvider and
myfilter!dispatch_request.

3: kd> k

Child-SP RetAddr Call Site

00 ffffd000dcf069a8 fffff8016b35d892 nt!KeBugCheckEx
01 ffffd000dcf069b0 fffff8016b393b6b nt!KiBugCheck3+0x12
02 ffffd000dcf069e0 fffff800c52a90b4 nt! ?? ::FNODOBFM::string'+0x25dab ;this is IofCallDriver 03 ffffd000dcf06a10 fffff800c52a5b60 myfilter!tcp_TdiReceive+0x22c 04 ffffd000dcf06a50 fffff800c52afd48 myfilter!dispatch_tcp+0x140 05 ffffd000dcf06a80 fffff800c432e764 myfilter!dispatch_request+0x2c 06 ffffd000dcf06ab0 fffff8016b2f4228 netbt!NbtWorkItemPostClientIrpToProvider+0x6c 07 ffffd000dcf06ae0 fffff8016b29e4bf nt!IopProcessWorkItem+0x80 08 ffffd000dcf06b50 fffff8016b30b554 nt!ExpWorkerThread+0x69f 09 ffffd000dcf06c00 fffff8016b363ec6 nt!PspSystemThreadStartup+0x58 0a ffffd000dcf06c60 00000000`00000000 nt!KiStartSystemThread+0x16

3: kd> !irp ffffe00208e69d00 1
Irp is active with 3 stacks 0 is current (= 0xffffe002088b2320)
Mdl=ffffe002087b8cd0: No System Buffer: Thread 00000000: Irp stack trace.
Pending has been returned
Flags = 00000000
ThreadListEntry.Flink = ffffe00208e69d20
ThreadListEntry.Blink = ffffe00208e69d20
IoStatus.Status = c0000016
IoStatus.Information = 000005b4
RequestorMode = 00000000
Cancel = 00
CancelIrql = 0
ApcEnvironment = 01
UserIosb = 00000000
UserEvent = 00000000
Overlay.AsynchronousParameters.UserApcRoutine = 00000000
Overlay.AsynchronousParameters.UserApcContext = 00000000
Overlay.AllocationSize = 00000000 - 00000000
CancelRoutine = 00000000
UserBuffer = 00000000
&Tail.Overlay.DeviceQueueEntry = ffffe00208e69d78
Tail.Overlay.Thread = 00000000
Tail.Overlay.AuxiliaryBuffer = 00000000
Tail.Overlay.ListEntry.Flink = 00000000
Tail.Overlay.ListEntry.Blink = ffffe002070c11f0
Tail.Overlay.CurrentStackLocation = ffffe002088b2320
Tail.Overlay.OriginalFileObject = 00000000
Tail.Apc = 07e58d80
Tail.CompletionKey = ffffe00207e58d80
cmd flg cl Device File Completion-Context
[IRP_MJ_INTERNAL_DEVICE_CONTROL(f), N/A(8)]
0 e0 ffffe002070c11f0 ffffe002088b2320
fffff800c4319690-ffffe002089c1720 Success Error Cancel
\Driver\myfilter netbt!NbtClientIrpCompletion
Args: 20000028b8 00000000 00000000 00000000
[IRP_MJ_INTERNAL_DEVICE_CONTROL(f), N/A(8)]
0 e0 ffffe00206480b20 ffffe001ff687dd0
fffff800c4a720b0-ffffe0020780bdf0 Success Error Cancel
\Driver\NetBT mrxsmb!RxTdiReceiveCompletion
Args: 00002e6c 00000000 00000000 00000000
[N/A(0), N/A(0)]
0 0 00000000 00000000 00000000-ffffe002086af010

Args: fffff800c3f1c180 fffff800c3f1c180 ffffe00208e69d00 20b46af0

Thanks Scott, that makes a lot of sense.

>Tail Call Optimization. Disassemble IofCallDriver and you’ll see that it ends in a JMP,

not a RET.
Got it.

I’m not sure about the issue you’re seeing
:frowning:

Alright, so I figured this one out. It turns out I was wrong about the execution path. This was a classical case of mrxsmb.sys sending an IRP that was too small, and my filter didn’t check to see if it was at the bottom of the stack before thrashing the IRP and attempting to call the next driver in the chain with it.

In the end I’m glad I got it fixed, but it turned out not to be a very interesting bug at all…