Best way to deal with user handle after process die.

Hi,

In our driver we need to inform user of certain events in the kernel driver, so the user creates a handle, proceed to send it to kernel via IOCTL, then in kernel mode we use ObReferenceObjectByHandle to get our kernel handle linked to the user one, then at the event we just signal the kernel one and user gets its own signaled too, this works.

How would be the best way to deal in the case that the user process die? how I can know if the handle is still valid? tracking the process id? we need to support multiple users so we don’t like the idea of creating many handles, if some of the current handles is stale, we would like to we use it, but how can we know?

First option for me would be to use ObDereferenceObject and then ObReferenceObjectByHandle again, if the call fails, the handle is not longer valid and I can flag it as stale for reuse.

Second option, track the process Id from the IOCTL and check if the process is still alive, but doesn’t feel good to track user pids.

I know there should be a clean and elegant way to deal with such cases.

Thanks in advance.

I know there should be a clean and elegant way to deal with such cases.

Yep. One of “you”, who designed this problematic interface should step out and explain why he/she hasn’t just used the good old inverted calls.

– pa

Pavel’s response is the right answer. Use an inverted call model and don’t mess with handles. WRT to your specific question, once you successfully call ObReferenceObjectByHandle the first time, the returned event pointer is valid until you ObDeref it. Your outstanding reference keeps the pointer valid beyond the lifetime of the sending process (again, until you drop the ref).

Thanks for the replies. The concept of inverted calls is an IOCTL waiting for completion basically? Like user sending the IOCTL and Kernel holding the response until the desired event happens?

Yes. The inverted call model provides your application the event to wait on AND it can provide and output buffer when the event is signaled in the completed IO request.

This looks interesting, because we have already the IOCT (to send the user Handle address). Ok abusing of your kindness, just one more question.

If Kernel is holding the IOCTL, what happens if the user wants to end the application? Or what if there is a segmentation fault in the application? The app cannot be done until Kernel releases the IOCTL right? Maybe I am misunderstanding something. Thanks once again.

Once it sends the IO request, the application has two choices: wait for it to complete or cancel it (usually the cancel comes after a timeout or another condition occurs). When the application exits, either normally or by crashing, the IO manager in the kernel will attempt to cancel all outstanding IO requests. This means you must support cancel in the driver. In WDF this is easy. For your pattern, when you receive the IOCTL you forward the request onto a manual WDFQUEUE. And when you want to complete the IOCTL later you remove it from the queue. While the request is parked in the manual WDFQUEUE it is cancelable and WDF handles all the cancelation logic. This has been covered by many articles and samples, start here.

If the application ends or crashes, the system will automatically flag a cancel request on all outstanding IRPs. Assuming the driver is well-written and/or uses KMDF, the driver will by notified of the cancellation request and will complete the IRPs. When the last IRP completes, the system can close the file handle.

The driver is WDM actually, let me research how to handle that case in WDM drivers.

Thank you both, very useful. I’ll implement a POC of this and get back if I have more questions.

You should not implement cancel support from scratch in your driver. Best bet is to port to WDF. Next best alternative is to use an IoCSQ in a WDM driver, https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-iocsqinitializeex

@Doron_Holan said:
You should not implement cancel support from scratch in your driver. Best bet is to port to WDF. Next best alternative is to use an IoCSQ in a WDM driver, https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-iocsqinitializeex

Unfortunately this is not an option, is a very large and very old driver, let me take a look at the IoCSQ, thank for the info once again.

You should consider this carefully. the reason why migrating to KMDF is recommended is that rewiring and porting a whole driver over is less work that properly supporting cancel for most drivers