I have just spent a some time debugging an issue, and I was was wondering, if someone has seen something similar.
The test case:
I have a kernel mode thread that, naturally, runs at PASSIVE_LEVEL
every now and then the thread wakes up and submits a packet using the ReceiveHandler function from the original NDIS_OPEN_BLOCK
sometimes IRQL remains at DISPATCH_LEVEL after the ReceiveHandler has returned
In any case, I have managed to work around the problem by explicitly lowering the IRQL to PASSIVE_LEVEL, but, this really looks like a bug somewhere… Almost like a piece of MS code assumes that the handler should run at DISPATCH_LEVEL… Or may be they forget to unlock a spinlock…
I think this happens when tcpip.sys handles a TCP+SYN, and a Send function is invoked directly with a SYN/ACK… but I am not completely certain.
This particular problem is detected by the driver verifier when submitting a packet from a DeviceIOControl handler, since IRQL is different on the way out of the handler.
Another similar thing happens when my thread calls KeWaitForSingleObject() and the verifier bitches about IRQL being too high.
Protocol driver expects that its ProtocolReceive handler is called at DISPATCH_LEVEL (refer the DDK documentation where it is explicitely specified “…ProtocolReceive runs at IRQL = DISPATCH_LEVEL…”).
Since protocol driver assumes that it was called at DISPATCH_LEVEL then it could use KeAcquireSpinLock/KeReleaseSpinLockFromDpcLevel, an example instead KeAcquireSpinLock/KeReleaseSpinLock or something similar. It is not a good sample but when called on DISPATCH_LEVEL both pairs work on the same way.