IRP Processing in Driver

Hi,
We have a legacy filter driver which crashes randomly. The crash occurs
while sending IRP_MJ_CLEAN

operation for my FileObject which was created using
IoCreateStreamFileObject. This FileObject is created
for IRP_MJ_DIRECTORY_CONTROL (IRP_MN_QUERY_DIRECTORY).

So I did the following steps:

  1. Call IoCreateStreamFileObject. Set FileNameBuffer.

I compared my code with the code outlined here :

http://www.osronline.com/showThread.cfm?link=78034

I feel that I have found the reason for crash but I want to confirm if that
is the reason.

The crash is occuring in nt!FsRtlNotifyFilterReportChange while accessing
FileNameBuffer in FileObject. As

outlined the in the code at the above link, we were also doing same thing.
We were freeing FileNameBuffer

before doing cleanup. But then there was comment that we need to do that
after cleanup.

Question :

  1. Shall we free the FileNameBuffer after Cleanup as mentioned below:

A couple of comments on my orignal posting… Defending the indefensible :wink:

There is a bug in the post-create freeing of the filename buffer. This
code should be moved to after the CLEANUP has completed. Why? 'cause either
NTFS or the CM may keep a copy of a pointer to this Unicode buffer. Freeing
it prematurely caused some interesting BugChecks in the Verifier in NTFS.
2) We are also not copying flags as mentioned in the code

// (Re-)init newly created FO

// cloneFileObject->Flags &= ~(FO_STREAM_FILE | FO_HANDLE_CREATED |
FO_CLEANUP_COMPLETE);
cloneFileObject->Flags = fileObject->Flags;
cloneFileObject->RelatedFileObject = fileObject->RelatedFileObject;
Is it required?

  1. After cleanup, we send the IRP_MJ_CLOSE. However this step is not
    mentioned. So do we require that step

or IO manager will send that when reference counts goes 0. So when we should
send IRP_MJ_CLOSE for our

FileObject. Do its require remving and setting FO_STREAM_FILE

  1. I searched the list for FsControl field in FileObject returned by
    IoCreateStreamFIleObject. I have seen

this comment:

Just so everyone is clear on this. With the introduction of the filter
manager it is now a requirement for

all file systems to use at least the COMMON_FCB_HEADER and we strongly
encourage all file systems to use

the AVANCED_FCB_HEADER. If there are released file systems that don’t and it
runs on W2K or later they need

to be fixed ASAP because the machine will crash when minifilters start being
released.

Neal Christiansen
Microsoft File System Filter Group Lead

We do not initialize FsContext field but we do set it to NULL after sending
down IRP_MJ_CLOSE. However, sometimes
we get crash in CacheManager while accessing the FsContext. So I think we
should not touch it.

Any help is greatly appreciated as we are having lot of crashes at customer
location.

Thanks
Ashish

>The crash is occuring in nt!FsRtlNotifyFilterReportChange while accessing FileNameBuffer in

FileObject. As
outlined the in the code at the above link, we were also doing same thing. We were freeing
FileNameBuffer
before doing cleanup.

What is the need for a filter driver to free anything in the file object?

Filters must not do this. The file object does not belong to them.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

FileNameBuffer is allocated and initialized by Me. So I think we I need to
free it. This is also what ismentioned in Code at the enclosed link.

Ashish

On Sun, Sep 6, 2009 at 3:12 AM, Maxim S. Shatskih wrote:

> >The crash is occuring in nt!FsRtlNotifyFilterReportChange while accessing
> FileNameBuffer in
> >FileObject. As
> >outlined the in the code at the above link, we were also doing same thing.
> We were freeing
> >FileNameBuffer
> >before doing cleanup.
>
> What is the need for a filter driver to free anything in the file object?
>
> Filters must not do this. The file object does not belong to them.
>
> –
> Maxim S. Shatskih
> Windows DDK MVP
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>
> —
> NTFSD is sponsored by OSR
>
> For our schedule of debugging and file system seminars
> (including our new fs mini-filter seminar) visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Hi,
I found something strange which I believe does not makes sense. Can
somebody shed light on it or is it a known issue with filter manager.

Here is the output of analyze -v

b94bbf38 808692a4 00000050 92144f8e 00000000 nt!KeBugCheckEx+0x1b
b94bbf88 80836c1a 00000000 92144f8e 00000000 nt!MmAccessFault+0x813
b94bbf88 80942ff0 00000000 92144f8e 00000000 nt!KiTrap0E+0xdc
b94bc08c f70b8d02 9b62afd8 93c58b18 e3ec2740
nt!FsRtlNotifyFilterReportChange+0x148
b94bc2ac f70b18d9 b94bc2c8 8a2e4680 9b618ee8 Ntfs!NtfsCommonCleanup+0x1fb5
b94bc41c 80840153 93c58718 8a2e4680 8ee62f38 Ntfs!NtfsFsdCleanup+0xcf
b94bc430 f7128c45 8ee62f38 89dbffbb 0000000b nt!IofCallDriver+0x45
b94bc458 80840153 9b618ee8 8a2e4680 89dbfde0 fltmgr!FltpDispatch+0x6f
b94bc46c b9638d01 89dbffbb 89dbfde0 00000000 nt!IofCallDriver+0x45
WARNING: Stack unwind information not available. Following frames may be
wrong.
b94bc4cc b9638de3 89e65028 9b618ee8 89dbffbb DxSpy+0xbd01
b94bc530 b963a698 89e65028 9b618ee8 89dbffbb DxSpy+0xbde3
b94bc5fc b9643c95 00000144 9b618ee8 8a010046 DxSpy+0xd698
b94bc62c b962fb6d 00000001 94fb6d48 9b618ee8 DxSpy+0x16c95
b94bc6c0 b963dbfd 9b618ee8 89dbfde0 89dbffbb DxSpy+0x2b6d
b94bc70c b963ddfb 8a1498f8 89b8c95c 8a1498f8 DxSpy+0x10bfd
b94bc734 8083ffb5 8a312ae8 89dbfde0 8a1498f8 DxSpy+0x10dfb
b94bc764 f706f1dc e16b9da0 00000000 b94bc978 nt!IopfCompleteRequest+0xcd
b94bc774 f70b15c7 b94bc994 89dbfde0 00000000 Ntfs!NtfsCompleteRequest+0xc8
b94bc978 f70b18d9 b94bc994 89dbfde0 9b618ee8 Ntfs!NtfsCommonCleanup+0x2377
b94bcae8 80840153 93c58718 89dbfde0 8ee62f38 Ntfs!NtfsFsdCleanup+0xcf
b94bcafc f7128c45 8ee62f38 89dbffdc 00000000 nt!IofCallDriver+0x45
b94bcb24 80840153 9b618ee8 89dbfde0 89dc0000 fltmgr!FltpDispatch+0x6f
b94bcb38 b963ff01 89dbffdc 89dc0000 89dbfdf0 nt!IofCallDriver+0x45
b94bcb6c b963cfa9 8a312ba0 89dbfde0 00000901 DxSpy+0x12f01
b94bcbdc b96419ef 8a312ae8 89dbfde0 b94bcc00 DxSpy+0xffa9
b94bcbec 80840153 8a312ae8 89dbfde0 89dbfde0 DxSpy+0x149ef
b94bcc00 8092ec0a 8a1fe2b0 8b9ece70 8a1fe2c8 nt!IofCallDriver+0x45
b94bcc30 8092b6af 8b144d88 8a312ae8 00030196 nt!IopCloseFile+0x2ae
b94bcc60 8092b852 8b144d88 00000001 8b9ece70 nt!ObpDecrementHandleCount+0xcc
b94bcc88 8092b776 8b0b8fb8 8a1fe2c8 000013c0
nt!ObpCloseHandleTableEntry+0x131
b94bcccc 8092b7c1 000013c0 00000000 b94bccf0 nt!ObpCloseHandle+0x82
b94bccdc b9d5b4a0 000013c0 8a15da38 e3be60a0 nt!NtClose+0x1b
b94bccf0 b9d620c9 000013c0 00000001 a0804d48 srv!SrvNtClose+0x28
b94bcd08 b9d97914 8a15da38 8a15da38 8a15da38 srv!UnlinkRfcbFromLfcb+0x4d
b94bcd24 b9d979da 8a15da38 8a15da38 8a15da38 srv!SrvCompleteRfcbClose+0x1df
b94bcd44 b9d9766e 8a15da38 8a15da00 8a7c3fa0 srv!CloseRfcbInternal+0xb6
b94bcd5c b9d675cb b9d5680c 8a7c3fa0 8a7db398 srv!SrvCloseRfcb+0x53
b94bcd78 b9d47e87 8a7c3fa8 8a7db360 b9d5b6c7 srv!SrvSmbClose+0x17d
b94bcd84 b9d5b6c7 00000000 8a2ba7a0 00000000 srv!SrvProcessSmb+0xb7
b94bcdac 80920833 007db360 00000000 00000000 srv!WorkerThread+0x138
b94bcddc 8083fe9f b9d5b602 8a7db360 00000000 nt!PspSystemThreadStartup+0x2e
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16
Everything started with IRP_MJ_CLEAN. In the completion routine of this
MajorFuntion, we create FileObject using IoCreateStreamFileObject() and then
perform

IRP_MJ_CREATE, IRP_MJ_DIRECTORY_CONTROL, IRP_MJ_CLEAN and then IRP_MJ_CLOSE.

I allocate buffer for FileName and set it in FileObject. It Crashes above in
CleanUp code (Not always so we are not able to find a pattern). The crash is
always while FilterManager trying to access FileName which we freed before
doing cleanup.

I looked at instruction of crash :

kd> ub 80942ff0
nt!FsRtlNotifyFilterReportChange+0x129:
80942fd3 0f844bd8ffff je nt!FsRtlNotifyFilterReportChange+0x5d2
(80940824)
80942fd9 a810 test al,10h
80942fdb 751e jne nt!FsRtlNotifyFilterReportChange+0x153
(80942ffb)
80942fdd 0fb7c1 movzx eax,cx
80942fe0 8b4d1c mov ecx,dword ptr [ebp+1Ch]
80942fe3 8b4904 mov ecx,dword ptr [ecx+4]
80942fe6 807b2e01 cmp byte ptr [ebx+2Eh],1
80942fea 0f8439ca0000 je nt!FsRtlNotifyFilterReportChange+0x142
(8094fa29)
0: kd> u 80942ff0
nt!FsRtlNotifyFilterReportChange+0x148:
80942ff0 66833c085c cmp word ptr [eax+ecx],5Ch

The bad data pointer came from ecx which came from ebp+1ch. So This was
passed in by
Ntfs!NtfsCommonCleanup. Dumping this address:

dd b94bc08c+1ch
b94bc0a8 b94bc020

This address looks on stack. So is Ntfs!NtfsCommonCleanup sending us some
stack variable which does not exists as Stack Range for it is b94bc2ac and
b94bc08c.

Does it makes sense or am I missing something.

Any pointers/help is greatly appreciated.

Thanks
Ashish

On Sun, Sep 6, 2009 at 9:48 AM, Ashish Goyal wrote:

> FileNameBuffer is allocated and initialized by Me. So I think we I need to
> free it. This is also what ismentioned in Code at the enclosed link.
>
> Ashish
>
> On Sun, Sep 6, 2009 at 3:12 AM, Maxim S. Shatskih <
> xxxxx@storagecraft.com> wrote:
>
>> >The crash is occuring in nt!FsRtlNotifyFilterReportChange while accessing
>> FileNameBuffer in
>> >FileObject. As
>> >outlined the in the code at the above link, we were also doing same
>> thing. We were freeing
>> >FileNameBuffer
>> >before doing cleanup.
>>
>> What is the need for a filter driver to free anything in the file
>> object?
>>
>> Filters must not do this. The file object does not belong to them.
>>
>> –
>> Maxim S. Shatskih
>> Windows DDK MVP
>> xxxxx@storagecraft.com
>> http://www.storagecraft.com
>>
>>
>> —
>> NTFSD is sponsored by OSR
>>
>> For our schedule of debugging and file system seminars
>> (including our new fs mini-filter seminar) visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
>

>I compared my code with the code outlined here :

http://www.osronline.com/showThread.cfm?link=78034

The code is very much doubtful, I have major doubts you can replace the file name in the file object, except in the reparse path.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Maxim,
Then what will be file name in FileoObject created by

IoCreateStreamFileObject ( NULL, pDO );
Note that NULL FileObject is passed in. So FileObject is created based on
DeviceObject.

Thanks
Ashish

On Sun, Sep 6, 2009 at 1:55 PM, Maxim S. Shatskih wrote:

> >I compared my code with the code outlined here :
> >http://www.osronline.com/showThread.cfm?link=78034
>
> The code is very much doubtful, I have major doubts you can replace the
> file name in the file object, except in the reparse path.
>
> –
> Maxim S. Shatskih
> Windows DDK MVP
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>
> —
> NTFSD is sponsored by OSR
>
> For our schedule of debugging and file system seminars
> (including our new fs mini-filter seminar) visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Ashish Goyal wrote:

Hi,
I found something strange which I believe does not makes sense. Can
somebody shed light on it or is it a known issue with filter manager.

This is not a known issue with filter manager. It is, as has already
been pointed out, a bug that the file name is being torn down
prematurely. Since directory change notifications are built off the
file path name, it seems natural/expected that it would be accessed in
this path.

  • M

Ashish Goyal wrote:

  1. After cleanup, we send the IRP_MJ_CLOSE. However this step is not
    mentioned. So do we require that step

or IO manager will send that when reference counts goes 0. So when we
should send IRP_MJ_CLOSE for our

FileObject. Do its require remving and setting FO_STREAM_FILE

The code snippet did this via ObDereferenceObject. You should not need
to explicitly roll a CLOSE Irp.

If I’m reading it correctly, the original post was triggered by somebody
being the victim of FO_STREAM_FILE being set and un-set. Repeating this
may easily find yet another victim. Note that that this was done in the
original code to enable IRP_MJ_CREATE to be sent. Stream file objects
were intended to be used by filesystems, who could manage their own
references without needing to issue create Irps.

Why are you using stream file objects at all?

  1. I searched the list for FsControl field in FileObject returned by
    IoCreateStreamFIleObject. I have seen

We do not initialize FsContext field but we do set it to NULL after
sending down IRP_MJ_CLOSE. However, sometimes

we get crash in CacheManager while accessing the FsContext. So I think
we should not touch it.

This sounds like a good time to use ObDereferenceObject instead. If I’m
reading this correctly, you’re rolling your own IRP_MJ_CLOSE, which will
not decrement the pointer count on the object. This object is still in
use (PointerCount > 1), so the outcome of this is tearing down
structures supporting an object which is in use (since the filesystem’s
references are decremented) and failing to decrement Ob’s reference,
so the FileObject will hang around forever.

This assumes that you NULL-ed out FsContext on close completion. If you
did so before close, issuing IRP_MJ_CLOSE is a no-op. In that case, you
NULL-ed out FsContext of a FileObject that was in use, then leaked it.

  • M