That’s makes sense. I just wasn’t sure when and why you’d see a file
object allocated from the stack.
Thanks for the explanation.
jerry
-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Tuesday, May 06, 2003 7:21 AM
To: File Systems Developers
Jerry,
If the file object is from the stack, it is a fake file object. Real
file objects are allocated (by the object manager) from non-paged pool.
Hence, testing if the address of the file object is from this thread’s
stack would be an indicator that this is a fake file object. Of course,
if someone posts the request to a different thread, this test would not
find the fake file object, but in general CREATE operations are
performed synchronously.
Fake file objects avoid the overhead of creating real file objects. So
any operation where you know there is no I/O (and hence no attempt to
bump reference on the file object) is safe for such fake file objects.
From what I can tell this includes operations that delete the file
(CREATE, SET_INFORMATION, CLEANUP, CLOSE - so no I/O) as well as
operations that are merely obtaining attribute information about the
file (CREATE, QUERY_INFORMATION, CLEANUP, CLOSE.) These are the two
cases I know about, but it is quite possible that there are other cases
where someone identified that this was not going to need a real file
object and optimized it out.
The gist of this is that the original decision (avoiding the creation of
a real file object) was a performance optimization. This probably
doesn’t make too much difference today, but we now have an OS with
pieces that are
14 years old.
Regards,
Tony
Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com
-----Original Message-----
From: Kelley, Jerry [mailto:xxxxx@nsisoftware.com]
Sent: Tuesday, May 06, 2003 7:03 AM
To: File Systems Developers
Subject: [ntfsd] RE: Problem cancelling CREATEs
Tony,
A couple of questions:
-
In an earlier e-mail, you said that the file object might appear to
come from the stack and still be fake. If that’s the case, how would the
example catch it?
-
One thing I missed is why would there be a fake file object used?
Under what circumstances would we see this?
-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Monday, May 05, 2003 4:19 PM
To: File Systems Developers
Nick,
I’ll work on developing an example that does this, probably just using
the filespy example. To test for this is actually pretty easy. You can
use IoGetStackLimits to establish the range of the stack for the current
thread.
Then check to see if the FileObject is within that range. You WILL see
such cases and this is an easy check to add to your filter…
Regards,
Tony
Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com
-----Original Message-----
From: Nicholas Ryan [mailto:xxxxx@nryan.com]
Sent: Thursday, May 01, 2003 9:34 PM
To: File Systems Developers
Subject: [ntfsd] RE: Problem cancelling CREATEs
It is true that FastFat does not bump the fobj during create, but this
fact doesn’t necessarily mean that it’s unsafe to do so. You seem to
think it is unsafe because there are system entities that pass
non-object file objects down through the create path. Can you point us
to the system code that does this?
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tony Mason
Sent: Thursday, May 01, 2003 5:50 PM
To: File Systems Developers
Subject: [ntfsd] RE: Problem cancelling CREATEs
Nick,
My point here is not that you cannot use IoCreateStreamFileObject (you
can) but rather that the entire idea of USING a file object that
arrived in your filter or your file system via IRP_MJ_CREATE for
anything other than create processing is just simply not supported in
the current model. I believe that if you examine FastFAT, you will
find that it does not reference file objects in the create handler.
Ted suggested replacing the file object in the IRP_MJ_CREATE.
My point is that you can’t do that and the more important point of
that analysis is that you cannot even safely bump the reference count
on the file object that arrives in an IRP_MJ_CREATE.
At any rate, my contention is that I can construct a test program that
will cause the original filter (and note that I have no idea which
filter did
this) that was performing a read/write in the IRP_MJ_CREATE path with
that file object to eventually crash the system.
Regards,
Tony
Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com
-----Original Message-----
From: Nicholas Ryan [mailto:xxxxx@nryan.com]
Sent: Thursday, May 01, 2003 8:23 PM
To: File Systems Developers
Subject: [ntfsd] RE: Problem cancelling CREATEs
File objects create with IoCreateStreamFileObject/Lite are real,
honest-to-goodness Object Manager objects. Any filter that conjures up
a file object should do it using this API and there shouldn’t be any
problems referencing it.
Are you saying there is code in the kernel that creates file objects
that aren’t real objects? This wouldn’t even be safe for the
filesystem, would it? There’s a couple places in the FastFat code
where a file object is referenced.
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Tony Mason
> Sent: Thursday, May 01, 2003 2:34 PM
> To: File Systems Developers
> Subject: [ntfsd] RE: Problem cancelling CREATEs
>
>
> Ted,
>
> Actually, reading this discussion and looking at this issue makes me
> wonder how applications that read from the file in the create path,
> using the file object in the IRP can work right at all - I’d argue
> that this is a fundamental bug in THEIR implementation, not in
> IoCancelFileOpen.
>
> This is because the file object passed in an IRP_MJ_CREATE is not
> necessarily a “real” file object. For whatever reason, there are
> callers who fake the file object (including the I/O Manager for
> certain query and delete operations). However, if the file object
> is fake in the IRP_MJ_CREATE path, how can it EVER be safe for a
> caller to use that file object for an IRP_MJ_READ? If that file
> object is used by the cache manager and/or memory manager, it will
> attempt to bump the reference count on the file object - but of
> course that “file object”
> isn’t really an object so it does not have an object header.
> Thus, the increment is on some random location in memory.
>
> Worse yet, those file objects appear to come from the stack.
> Thus, if it doesn’t blow up because you’ve bumped the reference
> count of something that isn’t a reference count, it is going to blow
> up when CC or MM try to dereference the file object since it isn’t a
> file object. Of course, this all might very well work since the
> stack might just simply be valid.
>
> Thus, I would suggest that anyone who has a filter using the file
> object in the IRP_MJ_CREATE for a subsequent IRP_MJ_READ or
> IRP_MJ_WRITE (both of which can interact with CC or MM) has a
> fundamental flaw in their filter - a lurking bug that will
> potentially bite them in the future.
>
> Thoughts?
>
> Regards,
>
> Tony
>
> Tony Mason
> Consulting Partner
> OSR Open Systems Resources, Inc.
> http://www.osr.com
>
>
> -----Original Message-----
> From: Ted Hess [mailto:xxxxx@livevault.com]
> Sent: Wednesday, April 30, 2003 11:28 AM
> To: File Systems Developers
> Subject: [ntfsd] RE: Problem cancelling CREATEs
>
> There is actually 2 different scenarios that have to be considered:
>
> 1. Stall original CREATE (pre-CREATE) and perform your own
> CREATE…“Cancel” operations on the side before deciding the fate of
> the original CREATE. It was this case that caused the problem we saw
> with a second filter because I “borrowed” the original FileObject.
> Your suggestion (probably from David G.) was just what I was
> planning on doing to fix this case.
>
> 2. Allow the original CREATE to complete then decide whether you
> want to cancel it or not in your completion routine. This case does
> not lend itself to the “clone a FileObject”
> solution – does it?
> - Pre-CREATE: Save FO1. Clone orignal FileObject -> FO2 &
> substitute in CREATE IRP
> - Post-CREATE:
> a. Decide to FAIL CREATE - Perform “Cancel”
> operations on FO2, restore FO1 in CREATE IRP. Return error status,
> IO Manager deletes FO1.
> b. Decide to allow CREATE - Return opened FO2 in CREATE
IRP? Dump
> FO1 – How??? ObDereferenceObject?
>
> Will this work!?
>
> /ted
>
> -----Original Message-----
> From: Nicholas Ryan [mailto:xxxxx@nryan.com]
> Sent: Saturday, April 26, 2003 3:08 PM
> To: File Systems Developers
> Subject: [ntfsd] RE: Problem cancelling CREATEs
>
>
> Hi Ted, great meeting you guys at the PlugFest. I spoke about this
> issue in detail with one of the MS guys - you can tell if Cc has a
> reference by calling CcGetFileObjectFromSectionPtrs and comparing
> the returned file object to your file object. However, it turns out
> that not only can the Cache Manager be holding a reference, so can
> the Memory Manager, and there is no corresponding Mm API. The long
> and short of it is that IoCancelFileOpen is a broken API
> - there is no way a filter can guarantee that nothing it does, let
> alone anybody under it, will not cause the reference on the fobj to
> increase.
>
> Option 2 won’t work because if you complete a create request with a
> failure status, upon return NT will just simply blow away the file
> object without regard to whether it has any reference outstanding or
> not. (See the thread ‘Implementing IoCancelFileOpen’ in the archives
> for a detailed explanation). This is why this whole thing is a bug
> in the first place.
>
> One suggestion was that if there was any possibility that your
> filter would want to cancel the create, it should roll its own fobj
> using one of the stream fobj APIs, and send THAT down. This fobj you
> can then cleanup and dereference and then forget about - because
> it’s not the IRP stack NT won’t blow it away, and you can rest
> assured it will be closed whenever the guy that has the last
> reference to it (if any) derefs it.
> I used to be skeptical of the roll-your-own create technique, but
> the MS guy I talked to said it was solid so now I’m warming up to
> it.
>
> - Nick Ryan
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Ted Hess
> Sent: Saturday, April 26, 2003 9:04 AM
> To: File Systems Developers
> Subject: [ntfsd] Problem cancelling CREATEs
>
>
> Many of us have had the need to cancel a CREATE in our completion
> routines after it has succeeded in the FSD. The standard technique
> is to issue a CLEANUP and CLOSE IRP and then return an appropriate
> error status to the CREATE.
> Alternatively one may use the IoCancelFileOpen() procedure available
> in Windows 2000 and later versions of the OS.
> However, it was observed during filter inter-op testing at the
> recent PlugFest at Microsoft that if two or more filters are
> involved and certain conditions arise, this technique is not
> reliable. In fact, a BugCheck in the cache manager may result. The
> scenario that fails involves 2 filters that behave as follows:
> 1. The top-filter’s CREATE dispatch issues a CREATE IRP (or merely
> passes one through) and sets a completion routine 2. The
> lower-filter intercepts the CREATE completion and then READs some
> portion of the file as it would for AV detection.
> 3. The lower-filter then completes the IRP (STATUS_SUCCESS) but the
> top-filter decides to FAIL the CREATE by issueing CLEANUP/CLOSE IRPs
> or calling IoCancelFileOpen(). The problem here is the FileObject
> involved now has an additional reference to it caused indirectly by
> the lower-filter setting up the cache-map in the FileObject when it
> issued the READ IRP. Sending a CLOSE IRP does not release this
> reference and it is possible to crash the Cache Manager if/when the
> FileObject gets re-used. Addtionally, it was observed that calling
> IoCancelFileOpen() in this scenario will cause a BugCheck in
> IoCancelFileOpen() due to the fact that it checks the FileObject
> reference count and BugChecks if it is not equal to 1! Solution
> discussion:
> 1. The top-filter could check the PrivateCacheMap pointer in the
> FileObject before cancelling the CREATE and attempt to purge the
> cache section however, it does not own reference and the pointer may
> not be valid since the FSD does not NULL it out! 2. Instead of
> issueing CLEANP/CLOSE IRPs, it was suggested to issue a CLEANUP and
> then call ObDereferenceObject(). If the reference count goes to zero
> a CLOSE will be issued and the FileObject deleted. There is still
> the issue of the lingering cache reference, but I believe this to be
> normal for a “closed” file. Comments??
> /ted
>
>
>
> —
> You are currently subscribed to ntfsd as: xxxxx@nryan.com To
> unsubscribe send a blank email to xxxxx@lists.osr.com
>
>
>
> —
> You are currently subscribed to ntfsd as: xxxxx@livevault.com To
> unsubscribe send a blank email to xxxxx@lists.osr.com
>
>
> —
> You are currently subscribed to ntfsd as: xxxxx@osr.com To
> unsubscribe send a blank email to xxxxx@lists.osr.com
>
> —
> You are currently subscribed to ntfsd as: xxxxx@nryan.com To
> unsubscribe send a blank email to xxxxx@lists.osr.com
>
You are currently subscribed to ntfsd as: xxxxx@osr.com To unsubscribe
send a blank email to xxxxx@lists.osr.com
You are currently subscribed to ntfsd as: xxxxx@nryan.com To
unsubscribe send a blank email to xxxxx@lists.osr.com
You are currently subscribed to ntfsd as: xxxxx@osr.com To unsubscribe
send a blank email to xxxxx@lists.osr.com
You are currently subscribed to ntfsd as: xxxxx@nsisoftware.com To
unsubscribe send a blank email to xxxxx@lists.osr.com
You are currently subscribed to ntfsd as: xxxxx@osr.com
To unsubscribe send a blank email to xxxxx@lists.osr.com
You are currently subscribed to ntfsd as: xxxxx@nsisoftware.com
To unsubscribe send a blank email to xxxxx@lists.osr.com