Stream Context between multiple MiniFilter instances

Well, that’s not usually the problem (that the filter doesn’t have a file to work with) but rather that a filer above yours might operate on the wrong file. I don’t know exactly where you sit in the altitude list, but assuming an antivirus is installed above your filter on V2, it will see the GUID file name in preCreate. If it tries to scan the file then it needs to get to the right one otherwise it might miss malicious files (if you create bogus files and not fix the names properly, then it might scan those). The same might be the case for an encryption filter that only encrypts .doc files… If they see the name as a GUID, then they might not know they need to decrypt the file…

There is yet another problem… In replacing the GUID with the actual name when the IRP_MJ_CREATE reaches your minifilter, you are effectively injecting that name in the middle of the IO stack. However, names belong at the top of the stack, because you have no guarantees that the namespace looks the same way at all levels. For example, imagine a minifilter above yours which implements a flat namespace on the volume consisting only of IDs and where it maintains the illusion of a hierarchical namespace by keeping track of ID to name mapping at its level. If this minifilter is above yours then the “\foo\bar.txt” file which might be exposed at the top of the stack simply doesn’t exist at your level… If you think this is too crazy of a scenario, keep in mind that in vista and newer OSes there is an inbox microsoft minifilter that does something pretty similar for some files (I’m talking about luafv.sys).

Now, I can’t tell whether these are minor or major problems (this is usually between you and your customers… perhaps their environment is locked down enough that there is never another filter loaded… )… All I can do is point out possible things to be concerned about.

Thanks,
Alex.

I have seen file-system virtualization filters that effectively strip off the ECPs when they notice a STATUS_REPARSE, so ECPs aren’t even a perfect solution on Windows 7. In general, its much easier if you only store advisory information in the ECP. For example, I had lengthy bit of processing to do prior to reparsing the create to the correct volume, so I cache that work in the ECP. If the ECP made it through the reparse handling, GREAT, if not, well, it slowed down the second part of the create. Perhaps this behavior is actually a bug in that filter… I dunno… maybe they did it on purpose for some other reason.

AFAIK, a create operation will be fully processed within a single thread context. If you only need to cache information, then you could have a global map (protected by a lock obviously) going from thread-id to “your information”. Then when you saw the request on the second volume, you could check to see if it was related to the per-thread cached request. This would still have some holes, because a program could … “open C:\A, then you reparse to D:\A, then some filter fails the request, then the app could open D:\A just because” … and then you wouldn’t have the correct behavior.

I saw a mention somewhere that pre-vista OS’s use the extended attributes fields to pass some information down for the filter manager (would have been done with ECPs on the newer OS). Maybe if you manipulate the EA list it will be propagated across the reparse on the older OS’s? Perhaps this is just a variant on what Alex proposed (manipulating the security contexts… some part of which will be propagated across reparses).

I think a filter that does that is broken. IO manager relies on those ECPs
being preserved in some scenarios.

You’re right that the thread context is the same for IO issued by the IO
manager. But there are no guarantees around it and in fact there are filters
that break this by pending IRP_MJ_CREATEs in preCreate and then completing
them in a different thread. So if you happen to be below such a filter, you
will see a different thread than the one where IO manager issued the create
at the top of the stack. And there is still the issue of the failed
STATUS_REPARSE and a new request coming in on the same thread (and that does
happen quite a lot in some environments… like SRV for example).

I don’t think EAs would work, because I think that the IO manager would
repopulate the EA buffer and EaLength from the open packet on each
subsequent CREATE operation. I’m pretty sure the original EA and EaLength
don’t get updated in a STATUS_REPARSE case, and even if they did, the IO
model has no mechanism by which updates to the IO_STACK_LOCATION get
propagated back up during IRP completion, meaning that setting them in the
current stack location will not propagate them up to the IO manager anyway.

I’m pretty sure the security context could be used in this manner. The thing
that makes this work (potentially) is that the security context is captured
early on (so subsequent reparses still happen in the same context) which
means it’s probably going to be unchanged throughout the call. Also, it is a
pointer to a buffer as opposed to a value, which means that changing
something in the buffer (but not the buffer itself) should be persistent
across calls. Still a hack though, but if this restricted to XP only (ECPs
are still the better option in Vista+) and if changes to the security
context still keep it consistent, then I think it has a fairly good chance
of success.

Thanks,
Alex.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@moka5.com
Sent: Tuesday, September 21, 2010 9:49 PM
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] Stream Context between multiple MiniFilter instances

I have seen file-system virtualization filters that effectively strip off
the ECPs when they notice a STATUS_REPARSE, so ECPs aren’t even a perfect
solution on Windows 7. In general, its much easier if you only store
advisory information in the ECP. For example, I had lengthy bit of
processing to do prior to reparsing the create to the correct volume, so I
cache that work in the ECP. If the ECP made it through the reparse
handling, GREAT, if not, well, it slowed down the second part of the create.
Perhaps this behavior is actually a bug in that filter… I dunno… maybe
they did it on purpose for some other reason.

AFAIK, a create operation will be fully processed within a single thread
context. If you only need to cache information, then you could have a
global map (protected by a lock obviously) going from thread-id to “your
information”. Then when you saw the request on the second volume, you could
check to see if it was related to the per-thread cached request. This would
still have some holes, because a program could … “open C:\A, then you
reparse to D:\A, then some filter fails the request, then the app could open
D:\A just because” … and then you wouldn’t have the correct behavior.

I saw a mention somewhere that pre-vista OS’s use the extended attributes
fields to pass some information down for the filter manager (would have been
done with ECPs on the newer OS). Maybe if you manipulate the EA list it
will be propagated across the reparse on the older OS’s? Perhaps this is
just a variant on what Alex proposed (manipulating the security contexts…
some part of which will be propagated across reparses).


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