Incorrect behaviour in Cdfs causes deadlock

Hi,

Since Windows XP SP2 I have an undesired interaction with cdfs.sys in my
filter driver, causing a deadlock.

My filter is attached over Cdfs volume device objects filtering
IRP_MJ_CLEANUP. During cleanup processing I build an Irp with
IoBuildAsynchronousFsdRequest, and set the required fields to send an
IRP_MJ_QUERY_INFORMATION (FileNameInformation) to Cdfs via IoCallDriver
routine. This implementation works perfectly, and it does not matter
actually what class of file information is requested from Cdfs to reproduce
this deadlock.

The problem arises when the user is browsing the cdrom, and suddenly remove
the media using the physical button. This is the observed behaviour:

When the user remove the media an immediate cleanup is intercepted in my
filter, and consequently my own QUERY_INFORMATION irp is sended to Cdfs to
get the file name for this cleanup irp.

Cdfs processing is heavily directed by exception handling. First, it founds
in CdVerifyFcbOperation that DO_VERIFY_VOLUME is set in the RealDevice, so
it raises an exception with exception code STATUS_VERIFY_REQUIRED. Cdfs
exception handler calls CdPerformVerify, which calls IoVerifyVolume and
ultimately the irp is completed correctly by Cdfs with
STATUS_NO_MEDIA_IN_DEVICE. CdPerformVerify raises a new exception, this time
with exception code STATUS_NO_MEDIA_IN_DEVICE, and from CdProcessException
the original QUERY_INFORMATION is pended and IoRaiseHardError routine is
called. HardErrorsAreDisabled == 0, so a normal kernel APC will be queued.

When cdfs finish irp processing, KernelApcDisabled == -1 due to
ObpCloseHandle always entering in a critical region.

Deadlock now exists. The I/O request will be completed in the normal kernel
APC. The normal kernel APC created by IoRaiseHardError waits for normal
kernel APCs to be enabled. The filter driver waits on completion of the I/O
request before it allows ObpCloseHandle to reenable normal kernel APCs.

This behaviour differs from Windows XP SP1. The QUERY_INFORMATION is
completed synchronously by Cdfs as DO_VERIFY_VOLUME is not set in the
RealDevice. In XP SP2 this flag is set by CLASSPNP as can be seen in the
stack:

805507ac f87d66bd 82dbe578 82f829b8 805507d3
CLASSPNP!ClasspInterpretGesnData+0x276
805507d4 804e42cc 82dbe4c0 82ef0e70 82dfd690
CLASSPNP!ClasspMediaChangeDetectionCompletion+0xca
80550804 f86c065e 82f9aef8 82fd80e8 00000000 nt!IopfCompleteRequest+0xa2
80550830 f86c0b94 82ef0e70 82f9aef8 805508ab
atapi!IdeProcessCompletedRequest+0x664
805508ac 804dc179 82fd80a4 82fd8030 00000000
atapi!IdePortCompletionDpc+0x204
805508d0 804dc0ed 00000000 0000000e 00000000 nt!KiRetireDpcList+0x46

I am thinking about a workaround to avoid this deadlock. As
KeAreApcsDisabled routine will always returns TRUE in XP during cleanup
processing, the unique solution would be to call IoSetThreadHardErrorMode to
FALSE before the call to Cdfs.sys, and revert the thread hard error mode
after it.

This is my question, is this deadlock considered to be cdfs.sys
responsibility?

Apart from all this, is correct to receive MJ_CLEANUP in APC_LEVEL irql?
Cdfs originates this frequently, although the DDK says MJ_CLEANUP is ALWAYS
received in PASSIVE_LEVEL in a file system filter driver.

Thanks,
mK


Express yourself instantly with MSN Messenger! Download today it’s FREE!
http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/