IoReleaseRemoveLock race



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.

.



Relevant Pages

  • Re: Propagating the Pending Bit
    ... If a driver sets an IoCompletion routine for an IRP and then passes the IRP ...
    (microsoft.public.development.device.drivers)
  • Re: Extra reference/remove-lock and completion routines
    ... a driver should call IoReleaseRemoveLock in the ... IoCompletion routine, after calling IoCompleteRequest." ... higher driver's dispatch routine is entered ... lower driver calls IoCompleteRequest ...
    (microsoft.public.development.device.drivers)
  • Re: Copying a kernel routine
    ... OH, lets see, you are going to modify the page table, but not the internal ... If you need a kernel like routine, design your own, but of course as I said ... Windows 2k/XP/2k3 Filesystem and Driver Consulting ...
    (microsoft.public.development.device.drivers)
  • Re: Copying a kernel routine
    ... and copy the kernel routine into this address. ... Windows 2k/XP/2k3 Filesystem and Driver Consulting ... What i am thinking is i can allocate a non-paged pool, ...
    (microsoft.public.development.device.drivers)
  • Re: A tough problem : Error -2539
    ... Why are you selecting a laser printer driver for an impact printer? ... The routine *appears* to check the attached peripherals, ... keyboard, disk drives, and the like. ... I think my sister managed to install it. ...
    (comp.sys.mac.misc)