My File is being kept alive, but I don't know why

Hello,

Context :
Windows 8.1
Minifilter
NTFS volume

On my post IRP_MJ_CREATE callback, I create another handle by FltCreateFileEx2 with FILE_READ_ATTRIBUTES | SYNCHRONIZE, no share and OBJECT_ATTRIBUTES has OBJ_KERNEL_HANDLE.
If I close it just after the FltCreateFileEx2 everything turn well.
If i close it in the pre IRP_MJ_CLOSE callback of the original File, the system keep the file opened, and when I unload my minifilter, the file is released.

when I try !object on the FILE_OBJECT I have HandleCount: 0 PointerCount: 0

One assumes that the original file is cached, pinning the original FileObject, thus pinned MJ_CLOSE will never be called

I understand that someone keep one of my file, but I receive the MJ_CLOSE callback and the ref count is 0 after that, on my original FileObject and my second FileObject.

How can someone kept one file opened without reference on this file ?

This is it,

CcIsFileCached return true on my FILE_OBJECTs when the file is being kept alive by the system,
CcUnmapFileOffsetFromSystemCache can solve my issue or it’s some misconception of my project ?

Opening my second HANDLE with FILE_NO_INTERMEDIATE_BUFFERING do the job.

Thank you for this hint.

rod_widdowson I think I missunderstand something,

I read this from the documentation that IRP_CLOSE thread context is arbitrary and IRP_CLEANUP is non-arbitrary,
When I close my second handle from the IRP_CLOSE of the original handle, my file is kept open,
but when I close it in the IRP_CLEANUP of the original handle, my file is closed.

The documentation of FltClose say that it should not be used to close arbitrary handle.

The term arbitrary in arbitrary handle is the same as arbitrary in arbitrary thread context ?
Can’t I close handle with FltClose in arbitrary context ?

The term arbitrary in arbitrary handle is the same as arbitrary in arbitrary thread context ?

Good point. I had assumed (because its hard not to) that this is a kernel handle you are opening. (OBJ_KERNEL flags to InitializeObjectAtttributes) That has to happen.

Beyond that I still don’t completely understand whether it is the MJ_CLOSE (of the first file) that is not happening (which could be because of caching) or the fact that if you the FltClose you issue doesn’t work (which could be the handle type)

Yes I create my second with OBJ_KERNEL in InitializeObjectAtttributes,

In fact I see the two MJ_CLOSE.
When the file is not cached (CcIsFileCached return false), after the MJ_CLOSE, my file is closed.
When the file is cached, after the MJ_CLOSE, my file is opened, but not by me.

If I understand the FileSystem correctly, when the MJ_CLEANUP occur the CacheManager Flush the unwritten cache on the disk.
It is possible that if I close my OBJ_KERNEL handle in MJ_CLOSE with arbitrary context, this context is used in the MJ_CLEANUP (which need non arbitrary context) and the CacheManager hang on the Flush ?

I think the problem occur in the CacheManager, because my minifilter don’t leak anything, don’t hang on DriverUnload and when it’s unloaded, the FileObject I don’t own is released.

Oups sorry, I don’t see the MJ_CLOSE for the kernel handle, my bad…
My ref count == 0, but the FileObject is not released correctly

My ref count == 0, but the FileObject is not released correctly

WHICH reference count? You know that there’s an object pointer reference count and a count of open handles – and they are separate, right?

Peter

In addition to questions and comments by others, in general, if you are implementing a shadow file technique, you would close the HANDLE of your underlying file during IRP_MJ_CLEANUP processing of the upper file. Then dereference your file object during the IRP_MJ_CLOSE processing of the upper file. Of course, this is a general rule but could alter depending on your requirements, etc.

Pete

Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

@“Peter_Viscarola_(OSR)” Both.
@Peter_Scott Why ? Is there specific behavior in closing the shadow file in MJ_CLOSE of the upper file ? I see there is a difference, but I don’t understand why.

If I think correctly,

It’s not impossible to see the MJ_CLOSE after a long time if the CacheManager keep the Section in cache for future use (pointer reference != 0),
but when I close the HANDLE, the MJ_CLEANUP is triggered immediately (handle count == 0).

But in my case the pointer ref == 0 and handle count == 0.
So I expect to see MJ_CLEANUP and MJ_CLOSE.

I see both when I release my Shadow file in the MJ_CLEANUP of the upper file.
I don’t see MJ_CLOSE of my Shadow file when I release it in the MJ_CLOSE of the upper file.

As I indicated, this is not a rule but if you are using shadow file objects, you open it at the time of IRP_MJ_CREATE, you close the handle at the time of IRP_MJ_CLEANUP and you dereference your file object when you get the IRP_MJ_CLOSE. You do this to reflect what is happening to the upper file object. So when the handle count goes to zero, that is when all processes have called CloseHandle() or some variant on the handle, you get the IRP_MJ_CLEANUP. When the file object count goes to zero, you get the IRP_MJ_CLOSE.

Again, I have implemented many layered file systems where this rule does not apply, it depends on your design.

Pete

Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

Okay I understand that now, I will try this way in my project
Thank you for all guys