FsRtlLookupPerStreamContext() unexplained behavior

Hi

I’m writing a legacy file system filter and need to keep track of file names for connecting paging I/O writes to ‘real’ file names and I’m using per-stream contexts for that.
More precisely, I’m allocating memory for a FSRTL_PER_STREAM_CONTEXT structure + a pointer to the file name at its end and passing that address to FsRtlInitPerStreamContext() and FsRtlInsertPerStreamContext(), retrieving the pointer to the struct along with the file appended name with FsRtlLookupPerStreamContext() when needed. Things are working ok but while trying to understand when it’s safe to free the per-stream context, I’ve noticed that FsRtlLookupPerStreamContext() sometimes returns contexts with ‘bad’ file names (i.e. not inserted by my driver). Trying to figure this out and eliminate the possibility that somehow another driver inserts contexts with the same ids (I’m normally passing device extension as ownerid), in the init/lookup functions I’m using pointers to some dummy static strings for ownerid and instanceid parameters but the behavior is unchanged.
What am I doing wrong and/o missing?

Well, I’d start by using ExAllocatePoolWithTag() and checking the tag of
the buffer actually matches. Also, I’d run with Driver Verifier and the
special pool option enabled (
http://msdn.microsoft.com/en-us/library/windows/hardware/ff551832(v=vs.85).aspx).
This should tell you a little more about what’s actually going on.

Now, you say you’re “trying to understand when it’s safe to free the
per-stream context”. Basically, in the simplest cases you don’t need to
this at all, the underlying filesystem will take care of that for you. See
the comments for FsRtlRemovePerStreamContext (
http://msdn.microsoft.com/en-us/library/windows/hardware/ff547238(v=vs.85).aspx),
from which I quote:

"
When a file stream is closed, the file system is responsible for ensuring
that all per-stream contexts associated with that stream are removed and
freed. To do this, the file system must call FsRtlTeardownPerStreamContexts
on the file control block (FCB) or other stream context object for the file
stream. FsRtlTeardownPerStreamContexts walks the FilterContexts list,
removing each entry and calling its FreeCallback routine.
Thus, a file system filter driver should not call
FsRtlRemovePerStreamContext from within an IRP_MJ_CLOSE or IRP_MJ_PNP
dispatch routine. Not only would such a call be unnecessary, but it might
also interfere with the file system’s call to
FsRtlTeardownPerStreamContexts.
Note A file system filter driver should not call
FsRtlRemovePerStreamContext from within a per-stream context structure’s
FreeCallback routine. This is because the underlying file system calls the
FreeCallback routine after it has already removed the context structure
from the FilterContexts list.
"

Another thing to note is a lot of these FsRtls are macros, so it’s worth
checking out the header files to get a better understanding of what’s
going.

And finally, I have two blog posts that might help paint the whole picture:
http://fsfilters.blogspot.com/2011/01/contexts-in-legacy-filters-and.html
and
http://fsfilters.blogspot.com/2012/09/a-helpful-debugging-technique-debug.html
(this last one has some code to set a context, though it’s a very simple
case).

Thanks,
Alex.

On Fri, Sep 26, 2014 at 6:21 AM, wrote:

> Hi
>
> I’m writing a legacy file system filter and need to keep track of file
> names for connecting paging I/O writes to ‘real’ file names and I’m using
> per-stream contexts for that.
> More precisely, I’m allocating memory for a FSRTL_PER_STREAM_CONTEXT
> structure + a pointer to the file name at its end and passing that address
> to FsRtlInitPerStreamContext() and FsRtlInsertPerStreamContext(),
> retrieving the pointer to the struct along with the file appended name with
> FsRtlLookupPerStreamContext() when needed. Things are working ok but while
> trying to understand when it’s safe to free the per-stream context, I’ve
> noticed that FsRtlLookupPerStreamContext() sometimes returns contexts with
> ‘bad’ file names (i.e. not inserted by my driver). Trying to figure this
> out and eliminate the possibility that somehow another driver inserts
> contexts with the same ids (I’m normally passing device extension as
> ownerid), in the init/lookup functions I’m using pointers to some dummy
> static strings for ownerid and instanceid parameters but the behavior is
> unchanged.
> What am I doing wrong and/o missing?
>
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars 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

Unfortunately this was a case of ‘find bug 2 mins after you post on forum’ (implementation-specific detail).
But things still don’t work as expected. For instance if I write to a file from a console (e.g. echo sometext > somefile.txt) I don’t see the IRP_MJ_CLOSE for that file, while if writing from (e.g.) Wordpad I get the expected close. Process Monitor sees the close for the console write tough.
Btw I ran into your blog while Googling for miscellaneous driver-related issues before, I’ll take a look.
Thanks.