I have an encryption isolation filter and it’s causing a crash (PAGE_FAULT_IN_FREED_SPECIAL_POOL) when I try to browse for a file through the new Edge browser. The crash happens in IoGetTransactionParameterBlock with the stack below.
My filter is not in the stack so I’m stuck on how to really debug it. Doing a little digging in IoGetTransactionParameterBlock (which is a small function), a FILE_OBJECT is passed in and it references the FileObjectExtension. Then if that is not null, it looks for something at an offset but the actual FileObjectExtension is opaque so not exactly sure what. In this case, it doesn’t really matter though because the FILE_OBJECT that is being passed is no longer valid. It is one of my filter’s FILE_OBJECTS (the upper one) but looking at my debug output, I can see that the FILE_OBJECT referenced by IoGetTransactionParameterBlock is closed right before this crash occurs.
The stack trace is consistent and it’s also interesting because the user mode functions in the stack are related to drives whereas the FILE_OBJECT was for a regular directory.
Seeing how the crashing function is related to transactions, I made some changes to see if it would stop the crash. I added a check in PreCreate to deny any transactions operations (FltObjects->Transaction != NULL) and I commented out some code in NormalizeName that deals with transactions. Neither helped because it still crashes.
So, like I said I’m stuck on where else to look or how to solve this. Any thoughts on the root cause or other areas to investigate would be appreciated.
To state the obvious you are obviously missing a path down to the file system. Name Providers and structures which take handles are a good place to look (there are a bunch of FSCTLs out there like MOVE_FILE - and the stack is indicative of that. Indeed a !irp will tell you a great deal.
I’m worried about this statement
it doesn’t really matter though because the FILE_OBJECT that is being passed is no longer valid
The only time a file object is no longer valid is when the reference count goes to zero and you get an MJ_CLOSE. I hope that’s what you mean…
One piece I left out is that I have stacked isolation filters running, one right on top of the other altitude-wise. The lower one does encryption while the higher one does other things. Doing some more testing, it appears there is a conflict between the shadow objects. In this case, the higher filter is closing it’s file objects but the lower file object is actually the upper file object for the lower altitude filter. That upper file object is the one being referenced by IoGetTransactionParameterBlock and causing the crash because it is no longer valid.
So, I guess the obvious question is, are stacked isolation filters allowed (or a good idea)? Will adding checks for FsContext2 in the lower object of the upper filter be enough to indicate whether it is actually the upper object of the lower filter and if so, just pass the request through?
Took me two days but figured out the root cause. When the upper filter created the lower object, the lower filter set FileContextSupportPointer in the FCB header to NULL. When the upper filter went to set a file context, it failed which in turn caused the pre-create to branch to a different path that did not clean things up properly (hence the invalid file object). So that is solved but my next issue is how to properly setup FileContextSupportPointer so that my lower filter does support file contexts. I’m trying to understand what is written about this pointer here (https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-fsrtlsetupadvancedheaderex) but it doesn’t make a lot of sense to me.
“FileContextSupportPointer must be a pointer to a PVOID variable inside a per-file structure for the file system that created the structure.”
I just allocated a PVOID and assigned it to that pointer and it seems to work but I’m wondering if that’s correct and all that needs to be done.
“FileContextSupportPointer must be a pointer to a PVOID variable inside a per-file structure for the file system that created the structure.”
If you are a filter (any structure) your “per file structure” is the FILE Context. In your case it is for the lower file system. Then you use the life cycle of that to drive the life cycle of the upper one (yours)