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

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:
  4. 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!
  5. 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

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:
  3. 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

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:
  3. 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

Sometimes I wonder if there were not too many Chefs in the kitchen when
they were brewing up the NT kernel.

Jamey

-----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:
  3. 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@storagecraft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

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.

  • Nick Ryan

-----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:
  4. 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

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.

  • Nick Ryan

-----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:
  4. 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

I think case 1 below has the advantage in terms of simplicity. The
additional create you are making is not connected in any way to the
blocked create - it has its own fobj and IRP - and thus you have to
worry less about how you’re affecting the original request. You have the
overhead of two creates in the case where you want the create to succeed
(and thus let the original IRP continue downwards), but that’s the way
it is.

I don’t think case 2 will work in the situation you want to substitue
fobj2 for fobj1 and succeed the create. You can swap out the file object
in your own stack location, but this won’t affect the value in the I/O
manager’s local variables.

  • Nick Ryan

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Ted Hess
Sent: Wednesday, April 30, 2003 8: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:
  4. 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@nryan.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

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?

  • Nick Ryan

-----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.

  • Nick Ryan

> -----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

If that’s the case then Tony, it sounds to me like there’s a need for
this test program in IOStress or possibly IFSTest if it can crash the
system quickly enough.

jerry

-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Thursday, May 01, 2003 7:50 PM
To: File Systems Developers

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.

  • Nick Ryan

-----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.
  2. 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:
  3. 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@nsisoftware.com To
unsubscribe send a blank email to xxxxx@lists.osr.com

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?

  • Nick Ryan

-----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.

  • Nick Ryan

> -----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

Tony,

A couple of questions:

  1. 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?

  2. 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?

  • Nick Ryan

-----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.

  • Nick Ryan

> -----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

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:

  1. 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?

  2. 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?

  • Nick Ryan

-----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.

  • Nick Ryan

> -----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

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:

  1. 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?

  2. 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?

  • Nick Ryan

-----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.

  • Nick Ryan

> -----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

Tony -

Let me see if I got this straight…

If one wants to cancel a CREATE from ones completion routine on an arbitrary
FileObject AND an underlying filter has performed READ/WRITE operations on
that FO, you are basically hosed???

In my two scenarios, this is #2 (fail original CREATE in post-CREATE).

In scenario #1 (fail original in pre-CREATE), we clone a FO via
IoCreateStreamFileObjectLite and use that as a probe to locate SCB/FCB. When
we done with it (no READ/WRITES in my filter!) we issue a CLEANUP and then
ObderefernceObject() and things will cleanup OK? The original CREATE/FO will
then be either failed or posted down to the FSD.

/ted

-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Thursday, May 01, 2003 8: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.

  • Nick Ryan

-----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:
  4. 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@livevault.com To unsubscribe
send a blank email to xxxxx@lists.osr.com

Ted,

Actually, what prompted my note was that in your scenario # 2 I started
thinking about your suggestion of replacing the file object. That then led
me to remember the case where the file object was allocated from stack
(delete file operations) and to realize that the second filter couldn’t
count on the file object being a real file object in the first place.

I’ve been thinking about the first scenario and believe that this is
probably the best one to choose. If you use IoCreateStreamFileObjectEx the
IRP_MJ_CLEANUP will be generated when you close the file object handle.
That means you don’t have to worry about reference counting since this now
works “the usual way”. I think that’s probably the cleanest approach.
Unfortunately, the Ex variant isn’t available on Windows 2000, so you’d have
to simulate the Ex variant or you’d need to explicitly send down your own
IRP_MJ_CLEANUP (as you suggested initially).

Of course, I would note that all you are doing is working around a bug in
another filter driver, since they should not have done I/O using that file
object in the first place.

For those who are building filters where you perform I/O in the
IRP_MJ_CREATE path, the best thing is to build a stream file object and use
THAT for your I/O, rather than relying upon some other filter driver to work
around the bug in your own filter driver.

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: Tuesday, May 06, 2003 12:50 PM
To: File Systems Developers
Subject: [ntfsd] RE: Problem cancelling CREATEs

Tony -

Let me see if I got this straight…

If one wants to cancel a CREATE from ones completion routine on an arbitrary
FileObject AND an underlying filter has performed READ/WRITE operations on
that FO, you are basically hosed???

In my two scenarios, this is #2 (fail original CREATE in post-CREATE).

In scenario #1 (fail original in pre-CREATE), we clone a FO via
IoCreateStreamFileObjectLite and use that as a probe to locate SCB/FCB. When
we done with it (no READ/WRITES in my filter!) we issue a CLEANUP and then
ObderefernceObject() and things will cleanup OK? The original CREATE/FO will
then be either failed or posted down to the FSD.

/ted

-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Thursday, May 01, 2003 8: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.

  • Nick Ryan

-----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:
  4. 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@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

I added an assert for this condition to my driver, and you’re right, I
am seeing stack-allocated file objects. On my machine, they are
generated internally by IopParseDevice (called indirectly by
NtQueryInformationFile) for use only within this function. Using this
file object, a create is sent down, then a fast I/O query basic info,
then a close.

One thing to note is that these still are valid OBJECTS, since they are
initialized on the stack with an _OBJECT_HEADER prefix by the system.
They can be referenced and dereferenced without fear of a blue screen.
Certainly you should not do anything in your create (or basic info)
dispatch to cause anyone else to take a reference to the file object,
however, since the object will not exist when the NtQueryInformationFile
call ends.

It does appear that the same ‘temporary’ file object is used across a
create/query/close triad, so that filters don’t have to worry about this
technique corrupting their file-object tracking mechanism (if they use
one).

  • Nick Ryan

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tony Mason
Sent: Monday, May 05, 2003 2:19 PM
To: File Systems Developers
Subject: [ntfsd] RE: Problem cancelling CREATEs

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?

  • Nick Ryan

> -----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.
>
> - Nick Ryan
>
> > -----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@nryan.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

As has been pointed out there are cases where the IOManager generates a
FILE_OBJECT on the stack and sends an IRP_MJ_CREATE (along with other
operations) down the file system stack using this local file object.

This is only done for query/delete type operations As Nicholas noted
these FILE_OBJECTS do have a valid OBJECT_HEADER.

The following system calls use this optimization:

NtDeleteFile
NtQueryAttributesFile
NtQueryFullAttributesFile
IoFastQueryNetworkAttributes (which is used by SRV)

The types of operations where you will see these fake file objects are:

IRP_MJ_CREATE
IRP_MJ_CLEANUP
IRP_MJ_CLOSE
IRP_MJ_QUERY_INFORMATION
FastIoQueryOpen
FastIoQueryBasicInfo
FastIoQueryStandardInfo
FastIoQueryNetworkOpenInfo

You must not do CACHED IO operations with these fake file objects. This
will cause the system to crash because MM will try and keep these file
objects around.

As Tony pointed out this was done several years ago for performance
reasons. There are no plans to change how this works.

Neal Christiansen
Microsoft File System Filter Group

This posting is provided “AS IS” with no warranties, and confers no
rights.

-----Original Message-----
From: Nicholas Ryan [mailto:xxxxx@nryan.com]
Sent: Tuesday, May 06, 2003 4:16 PM
To: File Systems Developers
Subject: [ntfsd] RE: Problem cancelling CREATEs

I added an assert for this condition to my driver, and you’re right, I
am seeing stack-allocated file objects. On my machine, they are
generated internally by IopParseDevice (called indirectly by
NtQueryInformationFile) for use only within this function. Using this
file object, a create is sent down, then a fast I/O query basic info,
then a close.

One thing to note is that these still are valid OBJECTS, since they are
initialized on the stack with an _OBJECT_HEADER prefix by the system.
They can be referenced and dereferenced without fear of a blue screen.
Certainly you should not do anything in your create (or basic info)
dispatch to cause anyone else to take a reference to the file object,
however, since the object will not exist when the NtQueryInformationFile
call ends.

It does appear that the same ‘temporary’ file object is used across a
create/query/close triad, so that filters don’t have to worry about this
technique corrupting their file-object tracking mechanism (if they use
one).

  • Nick Ryan

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tony Mason
Sent: Monday, May 05, 2003 2:19 PM
To: File Systems Developers
Subject: [ntfsd] RE: Problem cancelling CREATEs

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?

  • Nick Ryan

> -----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.
>
> - Nick Ryan
>
> > -----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@nryan.com
To unsubscribe send a blank email to xxxxx@lists.osr.com


You are currently subscribed to ntfsd as: xxxxx@windows.microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com