Reading files in pre close operation in filter driver

Hi,

I am working on a filter driver which need to check if a new executable is written to disk. To do that in pre close callback operation I am opening the file and read first few bytes to check if matches PE header structures. Everything seems to be working fine however it goes into a deadlock occasionally with below stack trace:

00 ffff828e0922f5f0 fffff8002b516c56 nt!KiSwapContext+0x76
01 ffff828e0922f730 fffff8002b51644b nt!KiSwapThread+0x2c6
02 ffff828e0922f800 fffff8002b515b6f nt!KiCommitThreadWait+0x13b
03 ffff828e0922f8a0 fffff8002b513ddd nt!KeWaitForSingleObject+0x1ff
04 ffff828e0922f980 fffff8002b51fea9 nt!ExpWaitForResource+0x6d
05 (Inline Function) ---------------- nt!ExpCommitWaitForResourceExclusive+0x1a 06 (Inline Function) ---------------- nt!ExpAcquireResourceExclusiveLite+0x185
07 ffff828e0922fa00 fffff80574046856 nt!ExAcquireResourceExclusiveLite+0x1c9
08 (Inline Function) ---------------- Ntfs!NtfsAcquirePagingResourceExclusive+0x13b 09 ffff828e0922fa90 fffff8057404f949 Ntfs!NtfsCommonCleanup+0x4b6 0a ffff828e0922ff50 fffff8002b641fc7 Ntfs!NtfsCommonCleanupCallout+0x19 0b ffff828e0922ff80 fffff8002b641f8d nt!KySwitchKernelStackCallout+0x27 0c ffff828e07f18d50 fffff8002b54fa3a nt!KiSwitchKernelStackContinue 0d ffff828e07f18d70 fffff8002b54f87e nt!KiExpandKernelStackAndCalloutOnStackSegment+0x12a 0e ffff828e07f18df0 fffff8002b54f735 nt!KiExpandKernelStackAndCalloutSwitchStack+0x9e 0f ffff828e07f18e60 fffff8002b54f6ed nt!KeExpandKernelStackAndCalloutInternal+0x35 10 ffff828e07f18ec0 fffff8057403cbc5 nt!KeExpandKernelStackAndCalloutEx+0x1d 11 (Inline Function) ---------------- Ntfs!NtfsCommonCleanupOnNewStack+0x51
12 ffff828e07f18f00 fffff8002b51d839 Ntfs!NtfsFsdCleanup+0x175
13 (Inline Function) ---------------- nt!IopfCallDriver+0x44 14 ffff828e07f19230 fffff80572ed7207 nt!IofCallDriver+0x59 15 ffff828e07f19270 fffff80572ed51c6 FLTMGR!FltpLegacyProcessingAfterPreCallbacksCompleted+0x157 16 ffff828e07f192e0 fffff8002b51d839 FLTMGR!FltpDispatch+0xb6 17 (Inline Function) ---------------- nt!IopfCallDriver+0x44
18 ffff828e07f19340 fffff8002b9b2a7e nt!IofCallDriver+0x59
19 ffff828e07f19380 fffff8002b9a6672 nt!IopCloseFile+0x15e
1a (Inline Function) ---------------- nt!ObpDecrementHandleCount+0x8a 1b ffff828e07f19410 fffff8002b9a3d6d nt!ObCloseHandleTableEntry+0x212 1c (Inline Function) ---------------- nt!ObpCloseHandle+0x9e
1d ffff828e07f19550 fffff8002b64f143 nt!NtClose+0xcd
1e ffff828e07f195b0 fffff8002b6424d0 nt!KiSystemServiceCopyEnd+0x13
1f ffff828e07f19748 fffff80572f04aba nt!KiServiceLinkage
20 ffff828e07f19750 fffff80575c24866 FLTMGR!FltClose+0xa
21 ffff828e07f19780 fffff80575c23497 PEMonFilter!IsExecutable+0x4866
22 ffff828e07f19950 fffff80572ed66fc PEMonFilter!FilemonClosePreOp+0x3497
23 ffff828e07f19aa0 fffff80572ed629c FLTMGR!FltpPerformPreCallbacks+0x2dc
24 ffff828e07f19bc0 fffff80572ed53b4 FLTMGR!FltpPassThroughInternal+0x8c
25 ffff828e07f19bf0 fffff80572ed51ae FLTMGR!FltpPassThrough+0x144
26 ffff828e07f19c50 fffff8002b51d839 FLTMGR!FltpDispatch+0x9e
27 (Inline Function) ---------------- nt!IopfCallDriver+0x44 28 ffff828e07f19cb0 fffff8002b9b2d04 nt!IofCallDriver+0x59 29 ffff828e07f19cf0 fffff8002b99e010 nt!IopDeleteFile+0x124 2a ffff828e07f19d70 fffff8002b523761 nt!ObpRemoveObjectRoutine+0x80 2b (Inline Function) ---------------- nt!ObfDereferenceObjectWithTag+0x92
2c ffff828e07f19dd0 fffff8002b9ece7e nt!ObfDereferenceObject+0xa1
2d ffff828e07f19e10 fffff8002b505182 nt!MiSegmentDelete+0x192
2e ffff828e07f19e70 fffff8002b5af496 nt!MiCheckControlArea+0x192
2f ffff828e07f19ed0 fffff8002b5ab7c4 nt!MmPurgeSection+0x746
30 ffff828e07f1a000 fffff8002b4a1f48 nt!CcPurgeCacheSection+0x94
31 ffff828e07f1a0c0 fffff80573f4b95a nt!CcCoherencyFlushAndPurgeCache+0xc8
32 ffff828e07f1a110 fffff80573ff3f98 Ntfs!NtfsCoherencyFlushAndPurgeCache+0x2e
33 ffff828e07f1a150 fffff805740379c1 Ntfs!NtfsFlushAndPurgeScb+0xa0
34 ffff828e07f1a1b0 fffff80574035344 Ntfs!NtfsOpenAttribute+0xad1
35 ffff828e07f1a2f0 fffff80574034e7e Ntfs!NtfsOpenExistingAttr+0x204
36 ffff828e07f1a3b0 fffff80574033281 Ntfs!NtfsOpenAttributeInExistingFile+0xa7e
37 ffff828e07f1a590 fffff80574044f33 Ntfs!NtfsOpenExistingPrefixFcb+0x1e1
38 ffff828e07f1a670 fffff8057404157e Ntfs!NtfsFindStartingNode+0xe93
39 ffff828e07f1a760 fffff80573f60119 Ntfs!NtfsCommonCreate+0xe8e
3a ffff828e07f1a9c0 fffff8002b546155 Ntfs!NtfsFspDispatch+0x309
3b ffff828e07f1ab00 fffff8002b4b8e27 nt!ExpWorkerThread+0xf5
3c ffff828e07f1ab90 fffff8002b645f76 nt!PspSystemThreadStartup+0x47
3d ffff828e07f1abe0 0000000000000000 nt!KiStartSystemThread+0x16

In pre close operation I am using calling below functions in order:
• FltCreateFile,
• ObReferenceObjectByHandle
• FltReadFile
• ObDereferenceObject
• FltClose

I searched in the forum to check if there are similar issues reported. Unfortunately could not find any. I attached debugger in the function in normal scenarios I could see NtClose in the stack trace, however when I run into issue, it looks like it is a system thread trying to flush some file data to disk. Are there any restrictions in reading files in pre close callback? For my understanding in what scenarios do we run into this issue?

Regards,
Vishnu.

Are there any restrictions in reading files in pre close callback?
You would appear to prove that there are.

In general you will very often get close when cc starts to clean things up and this will more than often mean that the underlying file system will have locks which will seriously get in your way.

I suppose if you were brave you could borrow the file object and try a paging read. I might be more inclined to do the check in cleanup and then monitor for writes at the special offset from then on.

I tried using the file object first and I ran into other set of issues. I am looking at moving the check to post clean up operation.