http://msdn2.microsoft.com/en-us/library/aa490593.aspx

In the documentation of IoReleaseRemoveLock, the directions for I/O
operations that set an IoCompletion routine include a race condition.
They could allow a driver to release the last known reference to its
own code, and if this happens then unpredictable behavior will result.

In this situation, if the lower driver happens to call
IoCompleteRequest from its dispatch routine then the completion
routine of the higher driver will be called, and if that then releases
the higher driver's remove lock then the higher driver's
IRP_MN_REMOVE_DEVICE handler could be allowed to proceed and
dereference the lower driver, all before the lower driver's dispatch
routine returns. The lower driver has just indirectly released the
last known reference to its own code.

In a graphical form:

higher driver's dispatch routine is entered
higher driver acquires its remove lock
higher driver calls IoCallDriver
lower driver's dispatch routine is entered
lower driver acquires its remove lock
lower driver calls IoCompleteRequest
higher driver's IoCompletion routine is entered
higher driver releases its remove lock
higher driver's IoCompletion routine returns
lower driver releases its remove lock
<no known reference to lower driver at this point>
lower driver's dispatch routine returns
higher driver's dispatch routine returns


There must be two remove lock acquires by the higher driver in this
situation. Where the current documentation says:

"For I/O operations (including power and PnP IRPs) that set an
IoCompletion routine, a driver should call IoReleaseRemoveLock in the
IoCompletion routine, after calling IoCompleteRequest.

For I/O operations that do not set an IoCompletion routine, a
driver should call IoReleaseRemoveLock after passing the current IRP
to the next-lower driver, but before exiting the dispatch routine."


the second sentence should read:

"... do _or_ do not set an IoCompletion routine ..."

with the implication that setting an IoCompletion routine requires
calling IoReleaseRemoveLock twice (in the IoCompletion routine and
also after passing the current IRP to the next-lower driver) and
correspondingly calling IoAcquireRemoveLock twice, since it cannot be
predicted whether the higher driver's IoCompletion routine will run
before or after the lower driver's dispatch routine has returned, so
that in any case the higher driver's remove lock will not be
completely released until the lower driver's dispatch routine returns.

Re: IoReleaseRemoveLock race by chris

chris
Mon Apr 23 19:29:23 CDT 2007

On Apr 23, 5:58 pm, BubbaGump <BubbaGump@localhost> wrote:

> In the documentation of IoReleaseRemoveLock, the directions for I/O
> operations that set an IoCompletion routine include a race condition.
> They could allow a driver to release the last known reference to its
> own code, and if this happens then unpredictable behavior will result.

You're still alive!


Re: IoReleaseRemoveLock race by BubbaGump

BubbaGump
Mon Apr 23 20:45:21 CDT 2007

On 23 Apr 2007 17:29:23 -0700, chris.aseltine@gmail.com wrote:

>On Apr 23, 5:58 pm, BubbaGump <BubbaGump@localhost> wrote:
>
>> In the documentation of IoReleaseRemoveLock, the directions for I/O
>> operations that set an IoCompletion routine include a race condition.
>> They could allow a driver to release the last known reference to its
>> own code, and if this happens then unpredictable behavior will result.
>
>You're still alive!

Time is an illusion. Death is a delusion. I am that am.


Re: IoReleaseRemoveLock race by BubbaGump

BubbaGump
Mon Apr 23 21:15:27 CDT 2007

On 23 Apr 2007 17:29:23 -0700, chris.aseltine@gmail.com wrote:

>On Apr 23, 5:58 pm, BubbaGump <BubbaGump@localhost> wrote:
>
>> In the documentation of IoReleaseRemoveLock, the directions for I/O
>> operations that set an IoCompletion routine include a race condition.
>> They could allow a driver to release the last known reference to its
>> own code, and if this happens then unpredictable behavior will result.
>
>You're still alive!

I don't tend to commit too much time to any one area before leaving to
explore something new, but often I return, with knowledge of but no
sense of how much time has passed.