User buffers with embedded pointers

I can’t seem to cause this kernel driver to fail, but it seems like it should.

This particular driver is an old software-only component that is quite old, but had been ported to KMDF before I became responsible for it. It has a couple METHOD_NEITHER IOCTLS that I need to preserve to maintain compatibility with older user mode software. Currently the driver is built with KMDF 1.9 to cover the OS versions it needs to be compatible with.

One of these IOCTLs passes in a user mode buffer containing a structure with an embedded pointer. Inspection of the EvtIoInCallerContext callback shows that the input buffer is being retrieved by WdfRequestRetrieveUnsafeUserInputBuffer() and locked down using WdfRequestProbeAndLockUserBufferForRead(), but no such processing is being performed for the structure pointed to by the embedded pointer (which is actually the head of a singly-linked list that gets traversed in the IOCTL’s handler, so there may be more than one buffer that needs locking).

It seems like this should be very fragile, since the IOCTL handler will only be able to read data from the embedded pointer if it’s running in the address context of the user process — which it must be doing. In my testing of this IOCTL, I have not seen any problems, even with multiple user processes calling into it.

This IOCTL is always being used synchronously, so there’s no overlapped I/O in play.

Any insight about why this IOCTL is getting lucky, and how its luck might possibly run out? Ideally I’d like to find a way to demonstrate the code has a practical issue before fixing it.

Thanks,
Dave

Any insight about why this IOCTL is getting lucky

This is because you are just lucky enough to always receive a valid address in context of the caller process…

and how its luck might possibly run out?

Well, receiving an invalid address from the userland is the most obvious scenario. Another scenario (admittedly a contrived one) is a filter driver that pends all IOCTLs, and passes them down to your driver in context of a dedicated system thread. In the latter case your driver may receive the requests in the wrong process context, with the obvious consequences for METHOD_NEITHER IOCTLs. Although this example is contrived, there is nothing that technically prevents it from occuring. This is why METHOD_NEITHER is generally considered as a “not really an optimal” option in itself…

Anton Bassov

As @anton_bassov said, you’ve been lucky. You can enforce your luck by using the KMDF InCallerContext callback to do your processing. If you do all of your UM memory access there, you should be fine.

Thanks for the quick feedback, Anton and Phil, it confirms my suspicions. It was surprising to me that it was working, but I don’t care to trust luck. Moving the processing to the EvtIoInCallerContext handler seems like the best defense.

Dave

And use try/except regardless :slight_smile:

Always good practice, Dejan, thanks!