CallDriver IRP crashing with access violation

Hi mates,

I am coding a proof of concept code that makes registration to be notified about GUID_DEVINTERFACE_VOLUME devices.

The first chunk of code is going fine. The driver is notified, and the Callback function is normally called. Nonetheless, the PDO Object got back by executing IoGetDeviceObjectPointer() with symlink contained in the NotificationInfoStruct is a Filter Driver, thus I'm not able to use it as IoGetDeviceProperty in the parameter to retrieve, for instance, the DevicePropertyDeviceDescription.

getDevicePointerStatus = IoGetDeviceObjectPointer(
notification_struct->SymbolicLinkName,
FILE_READ_DATA | FILE_WRITE_DATA,
&fileObject,
&PDObject);
if (!NT_SUCCESS(getDevicePointerStatus))
{
KdPrint(("SntX >> Error trying to retrieve PDObject"));
return STATUS_SUCCESS;
}

ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

Searching the Forum I found a user that faced a similar problem with his driver. The solution was sending an IRP_MN_QUERY_DEVICE_RELATIONS, the successful execution of which will return a pointer to the lower PDO in the Driver Stack in the Status.ioInformation struct. This PDO is the "real" Physical Driver which could be passed to the IoGetDeviceProperty(). Then i wrote the following code:

PIRP pIrp = IoAllocateIrp(PDObject->StackSize, FALSE);
if (pIrp == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
KdPrint(("\n SntX >> Device Object: %p", PDObject));
KdPrint(("\n SntX >> Device Type: %08x", PDObject->DeviceType));
KdPrint(("\n SntX >> Object Type: %04x", PDObject->Type));
KdPrint(("\n SntX >> DRIVER obj Name: %wZ", PDObject->DriverObject->DriverName));

PIO_STACK_LOCATION _IRPSP;
_IRPSP = IoGetNextIrpStackLocation(pIrp);
_IRPSP->MajorFunction = IRP_MJ_PNP;
_IRPSP->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
_IRPSP->FileObject = fileObject;
_IRPSP->Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;

NTSTATUS status = IoCallDriver(PDObject, pIrp);

The IoCallDriver traced by the WinDbg clearly shows that the driver stack received the IRP and forwarded it down. Nonetheless, the system crashed with the following traced access violation exception:

EXCEPTION_RECORD: fffffa019581eb28 -- (.exr 0xfffffa019581eb28)
ExceptionAddress: fffff8035b63ed97 (nt!KeInsertQueueApc+0x00000000000000b7)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 0000000000000220
Attempt to read from address 0000000000000220

WinDbg

STACK_TEXT:

fffffa019581ed60 fffff8035b63c7fa : 0000000020204d00 0000000000000000 fffffa019581ee69 0000000000000000 : nt!KeInsertQueueApc+0xb7
fffffa019581edf0 fffff8035b63c397 : ffffde8f4320e010 0000000000000000 0000000000000000 0000000000000000 : nt!IopfCompleteRequest+0x44a
fffffa019581eed0 fffff8036123d16e : ffffde8f4320e368 ffffde8f3b8e6d30 fffffa019581e9b0 0000000000000000 : nt!IofCompleteRequest+0x17
fffffa019581ef00 fffff8035b666e35 : ffff9386c4afe210 ffffde8f4320e010 ffffde8f474cd030 0000000000000000 : volmgr!VmPnp+0x15e
fffffa019581ef60 fffff80362006e04 : ffffde8f4320e010 ffffde8f474cd180 0000000000000002 0000000000000000 : nt!IofCallDriver+0x55
fffffa019581efa0 fffff80362069964 : 0000000000000000 0000000000000000 0000000000000000 ffffde8f4320e3b0 : fvevol!FveFilterSkip+0x44
fffffa019581efd0 fffff8035b666e35 : ffffde8f4320e010 0000000000000001 ffffde8f4320e010 ffffffffffffffff : fvevol!FveFilterPnp+0x84
fffffa019581f010 fffff803621fd373 : fffffa019581f2c0 fffff8035b82ae7c ffffde8f4320e010 ffffde8f3a486040 : nt!IofCallDriver+0x55
fffffa019581f050 fffff8035b666e35 : ffffde8f4320e010 0000000000000007 0000000000000000 0000000000000000 : iorate!IoRateDispatchPnp+0xa3
fffffa019581f080 fffff803620d6057 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : nt!IofCallDriver+0x55
fffffa019581f0c0 fffff8035b666e35 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : volume!VolumePnp+0x47
fffffa019581f0f0 fffff803620fd743 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : nt!IofCallDriver+0x55
fffffa019581f130 fffff8035b666e35 : 0000000000000000 fffffa019581f260 ffffde8f3eac9030 fffff8035b172829 : volsnap!VolSnapPnp+0xa3
fffffa019581f1c0 fffff80361734c25 : 0000000000000000 0000000000000000 ffffde8f41353590 fffff803616343df : nt!IofCallDriver+0x55
fffffa019581f200 fffff80361895eea : fffffa0195819000 0000000000000000 ffffde8f3eacb1b0 0000000000000000 : Ntfs!NtfsCallStorageDriver+0xc5
fffffa019581f280 fffff80361895cc9 : ffffde8f413938a8 0000000000000001 fffffa019581f3f0 0000000000000000 : Ntfs!NtfsCommonPnp+0x1c2
fffffa019581f350 fffff8035b666e35 : ffffde8f41353510 ffffde8f4320e010 fffffa0195820000 ffffde8f413938a8 : Ntfs!NtfsFsdPnp+0x1e9
fffffa019581f3e0 fffff8035b17a1fb : 746c465c6d657473 ffffde8f41353510 000000000000fffe 0000000000000000 : nt!IofCallDriver+0x55
fffffa019581f420 fffff8035b177e43 : fffffa019581f4b0 0000000000000000 0000000000000000 ffffde8f3c429ac0 : FLTMGR!FltpLegacyProcessingAfterPreCallbacksCompleted+0x15b
fffffa019581f490 fffff8035b666e35 : ffff9386d5ce5ea0 fffff8035b707240 fffffa019581f538 0000000000000001 : FLTMGR!FltpDispatch+0xa3
fffffa019581f4f0 fffff803802d131f : ffffde8f4320e010 fffffa019581f5b0 0000000000000065 0000000000000003 : nt!IofCallDriver+0x55
fffffa019581f530 fffff8035bb77343 : fffffa019581f8c8 0000000000000000 0000000000000000 ffffde8f46ff1d40 : sentiXirpDriver!SentiXPnPNotification+0x1af [D:\tech\SentiXirp\sentiXirpDriver\sentixXirpDriver.c @ 144]
fffffa019581f7f0 fffff8035bb77674 : ffff9386d5ce5ea0 fffff8035bbc8541 ffff9386ae1728c0 ffff9386d5ce5ea0 : nt!PnpNotifyDriverCallback+0x8f
fffffa019581f8a0 fffff8035bb4fb30 : ffff9386ae42f550 ffffde8f3a495900 ffffde8f43037040 ffffde8f3a495900 : nt!PnpNotifyDeviceClassChange+0x19c
fffffa019581f940 fffff8035b6b7bf5 : ffffde8f3a4959c0 ffffde8f43037040 fffffa019581fac0 fffff80300000000 : nt!PnpDeviceEventWorker+0x2b0
fffffa019581f9c0 fffff8035b74d487 : ffffde8f43037040 0000000000000536 ffffde8f43037040 fffff8035b6b7aa0 : nt!ExpWorkerThread+0x155
fffffa019581fbb0 fffff8035b819f64 : ffffca806058b180 ffffde8f43037040 fffff8035b74d430 8000000000000000 : nt!PspSystemThreadStartup+0x57
fffffa019581fc00 0000000000000000 : fffffa0195820000 fffffa0195819000 0000000000000000 0000000000000000 : nt!KiStartSystemThread+0x34

I'm sure that is a simple question for an experienced driver programmer, but i didn't make any progress no matter what I read or try to do.

Anyone can help me ?

Your code doesn't show you assigning a completion routine. That isn't the cause of your problem, but are you assuming the request is completed synchronously?

Are you actually a filter driver in the same stack, or are you calling across stacks? That is, will the "fileObject" you inserted be familiar to the volume stack?

Tim, thank you in advance,

I didn't assign any completion routine because I'm presuming (maybe, presuming wrong) that the completion routine is a kind of function needed only for drivers that are in the same device stack. Likewise, I assume (again, maybe assuming wrong) that the code is completed in a serialized way. Am I wrong? Do I need to code some code with PENDING_STATUS conditions and KeWaitForSingleObject()?

I'm calling across stacks. My device type is FILE_DEVICE_UNKNOWN (software driver) thus, it's not stacked in the volume stack. But I'm presuming that my fileObject is familiar to the volume stack because it was furnished by notificationInfoStruct filled by IoRegisterPlugPlayNotification with GUID_DEVINTERFACE_VOLUME.

I'm thinking that, maybe, synchronization be the problem. Do you think ?

best regards,

An IRP that you create must have a completion routine. When IopfCompleteRequest gets called, it goes back through the IRP stack locations looking to see who wanted to know about it. I BELIEVE what is happening here is that it went through the stack and found no one who was interested in a callback, then ran off the end of the IRP stack and tried to return to user mode. The KeInsertQueueApc is tried to attach the IRP to the thread's APC queue, but since your stack location is garbage, that failed.

You have to have a completion routine, even if all it does is return STATUS_MORE_PROCESSING_REQUIRED. That will cause your IoCallDriver to return, and you can free the IRP.

Yesterday, based on this thread, I returned to the ioSetCompletionRoutine doc and made a new reading of the documentation. Therefore, I wrote the routine Callback (as you oriented me now) and set it with all "invoke" parameters set to TRUE.

The Callback now is a "stub" function with a debug message and STATUS_SUCCESS return. The crash persisted. Today, I'll change the Callback function return code as you are orienting me and later bring us the results.

Thank u for the support, regards!

Tim,

Once I changed the Callback return code it ran perfectly. No BSOD.

The code hit exactly volmgr.sys then I used the pointer to retrieve device information. Nonetheless, the IoGetDeviceProperty still returns empty or null data no matter which DEVICE_REGISTRY_PROPERTY the code retrieves. But ok, I'll work on it.

Thank you, Tim

regards!