Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Sept/Oct 2019 Issue of The NT Insider available


Download PDF here: http://insider.osr.com/2019/ntinsider_2019_01.pdf

It’s a particularly BIG issue, too: 40 pages of technical goodness, ranging from WDF to Minifilters. Check it out.
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

Correctly filtering rename operations.

andreiandrei Member Posts: 4

As stated in the "Filter Driver Development Guide" chapter 11.2, FltGetDestinationFileNameInformation should be used in the pre callback for IRP_MJ_SET_INFORMATION, and FltGetTunneledName should be used in post in order to vaidate that the name retrieved in the pre operation was not affected by name tunneling.

When testing with mapped network drives I noticed that FltGetTunneledName always returns a FLT_FILE_NAME_INFORMATION (the result is not NULL), meaning that the name was affected by name tunneling. The initially retrieved name (in the pre callback) correctly pointed to the new (renamed) path. The name returned by FltGetTunneledName was always the initial path (before the rename)

I also noticed that FltGetDestinationFileNameInformation returns the correct path (after the rename) in the post operation callback. But, as stated in the documentation, FltGetDestinationFileNameInformation should be called in the pre operation callback.

Another approach that I've tried was calling FltGetFileNameInformation in the post opereation callback, but this also returned the original (not renamed) path.

What's interesting is that when testing with UNC paths (not mapped network drives) the problem didn't appear.

So far i've tested on windows 10 RS5 and windows 10 RS6.

  1. How can I retrieve the correct path for the file object in the IRP_MJ_SET_INFORMATION post callback for a FileRenameInformation.
  2. Why does FltGetTunneledName return the original name for renames on \Device\Mup
  3. Why does FltGetFileNameInformation always return the original name in the post-operation of a file rename on a mapped network drive.
  4. If i retrieve the name in the pre-operation callback and the post-operation callback succeedes, is the name still valid?

sample code that reproduces my issue: https://pastebin.com/MDfMyLQV
log output for both cases: https://pastebin.com/njCPw7vY

Comments

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 239
    Did you notice a very particular difference between the two cases in the output?
    Namely that one is using Hgfs (VMware's Host Shared Folders
    redirector) and the other is using SMB?

    You'll have a looooot of "fun" figuring all the cases here. FG(D)FNI
    have soooo many cases where they just work a tad differently, or fail
    and you have to revert to your own code to get the result. Add to that
    the fact that they only really work on Microsoft's FSes "properly"
    (imagine how many issues are present on other FSes)


    Good luck - you will need it. And if it feels like it works in all
    cases in less than 6 months, be ready for some crash dumps or at least
    incorrect behaviours.

    On 5/22/19, andrei wrote:
    > OSR https://community.osr.com/
    > andrei started a new discussion: Correctly filtering rename operations.
    >
    > As stated in the "Filter Driver Development Guide" chapter 11.2,
    > FltGetDestinationFileNameInformation should be used in the pre callback for
    > IRP_MJ_SET_INFORMATION, and FltGetTunneledName should be used in post in
    > order to vaidate that the name retrieved in the pre operation was not
    > affected by name tunneling.
    >
    > When testing with mapped network drives I noticed that FltGetTunneledName
    > always returns a FLT_FILE_NAME_INFORMATION (the result is not NULL), meaning
    > that the name was affected by name tunneling. The initially retrieved name
    > (in the pre callback) correctly pointed to the new (renamed) path. The name
    > returned by FltGetTunneledName was always the initial path (before the
    > rename)
    >
    > I also noticed that FltGetDestinationFileNameInformation returns the
    > correct path (after the rename) in the post operation callback. But, as
    > stated in the documentation, FltGetDestinationFileNameInformation should be
    > called in the pre operation callback.
    >
    > Another approach that I've tried was calling FltGetFileNameInformation in
    > the post opereation callback, but this also returned the original (not
    > renamed) path.
    >
    > What's interesting is that when testing with UNC paths (not mapped network
    > drives) the problem didn't appear.
    >
    > So far i've tested on windows 10 RS5 and windows 10 RS6.
    >
    >
    > * How can I retrieve the correct path for the file object in the
    > IRP_MJ_SET_INFORMATION post callback for a FileRenameInformation.
    > * Why does FltGetTunneledName return the original name for renames on
    > \Device\Mup
    > * Why does FltGetFileNameInformation always return the original name in the
    > post-operation of a file rename.
    > * If i retrieve the name in the pre-operation callback and the
    > post-operation callback succeedes, is the name still valid?
    >
    > sample code that reproduces my issue: https://pastebin.com/MDfMyLQV
    >
    > log output for both cases: https://pastebin.com/njCPw7vY
    >
    > --
    > Reply to this email directly or follow the link below to check it out:
    > https://community.osr.com/discussion/291343/correctly-filtering-rename-operations
    >
    > Check it out:
    > https://community.osr.com/discussion/291343/correctly-filtering-rename-operations
    >

    Note: The email was trying to reply to an invalid Discussion (291343).
  • andreiandrei Member Posts: 4

    I tested on my workplace environment and the issue reproduced with actual remote file shares (this time with both mapped network drives AND UNC paths). I noticed that whenever FltGetTunneledName returns a non-NULL result, the problem appears. FGFNI returns the original (before rename) path in the post callback.

    Shouldn't the original name be unavailable in a post-callback for a rename if the rename was successful?

    @Dejan_Maksimovic said:
    Did you notice a very particular difference between the two cases in the output?
    Namely that one is using Hgfs (VMware's Host Shared Folders
    redirector) and the other is using SMB?

    You'll have a looooot of "fun" figuring all the cases here. FG(D)FNI
    have soooo many cases where they just work a tad differently, or fail
    and you have to revert to your own code to get the result. Add to that
    the fact that they only really work on Microsoft's FSes "properly"
    (imagine how many issues are present on other FSes)

    Good luck - you will need it. And if it feels like it works in all
    cases in less than 6 months, be ready for some crash dumps or at least
    incorrect behaviours.

    On 5/22/19, andrei wrote:
    > OSR https://community.osr.com/
    > andrei started a new discussion: Correctly filtering rename operations.
    >
    > As stated in the "Filter Driver Development Guide" chapter 11.2,
    > FltGetDestinationFileNameInformation should be used in the pre callback for
    > IRP_MJ_SET_INFORMATION, and FltGetTunneledName should be used in post in
    > order to vaidate that the name retrieved in the pre operation was not
    > affected by name tunneling.
    >
    > When testing with mapped network drives I noticed that FltGetTunneledName
    > always returns a FLT_FILE_NAME_INFORMATION (the result is not NULL), meaning
    > that the name was affected by name tunneling. The initially retrieved name
    > (in the pre callback) correctly pointed to the new (renamed) path. The name
    > returned by FltGetTunneledName was always the initial path (before the
    > rename)
    >
    > I also noticed that FltGetDestinationFileNameInformation returns the
    > correct path (after the rename) in the post operation callback. But, as
    > stated in the documentation, FltGetDestinationFileNameInformation should be
    > called in the pre operation callback.
    >
    > Another approach that I've tried was calling FltGetFileNameInformation in
    > the post opereation callback, but this also returned the original (not
    > renamed) path.
    >
    > What's interesting is that when testing with UNC paths (not mapped network
    > drives) the problem didn't appear.
    >
    > So far i've tested on windows 10 RS5 and windows 10 RS6.
    >
    >
    > * How can I retrieve the correct path for the file object in the
    > IRP_MJ_SET_INFORMATION post callback for a FileRenameInformation.
    > * Why does FltGetTunneledName return the original name for renames on
    > \Device\Mup
    > * Why does FltGetFileNameInformation always return the original name in the
    > post-operation of a file rename.
    > * If i retrieve the name in the pre-operation callback and the
    > post-operation callback succeedes, is the name still valid?
    >
    > sample code that reproduces my issue: https://pastebin.com/MDfMyLQV
    >
    > log output for both cases: https://pastebin.com/njCPw7vY
    >
    > --
    > Reply to this email directly or follow the link below to check it out:
    > https://community.osr.com/discussion/291343/correctly-filtering-rename-operations
    >
    > Check it out:
    > https://community.osr.com/discussion/291343/correctly-filtering-rename-operations
    >

    Note: The email was trying to reply to an invalid Discussion (291343).

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 239
    via Email
    > I tested on my workplace environment and the issue reproduced with actual
    > remote file shares (this time with both mapped network drives AND UNC
    > paths). I noticed that whenever FltGetTunneledName returns a non-NULL
    > result, the problem appears. FGFNI returns the original (before rename) path
    > in the post callback.
    On an actual network it happened on an SMB share?
    Notice that the issue occurs on HGFS in your debug output, but not on
    SMB shares.


    > Shouldn't the original name be unavailable in a post-callback for a rename
    > if the rename was successful?
    Well, it should provide the cached file name, but I am not sure about
    the case of QUERY_FILE_SYSTEM_ONLY flag. I imagine it should NOT, but
    it might be playing some magic in that particular case.
    Technically, in all SUCCESSFUL post-rename cases, FGFNI should return
    the new file name. If it does not on SMB shares, it is one of its
    quirks.
    I sure doubt it has anything to do with caching, since FltMgr can
    request the file name directly.
  • rod_widdowsonrod_widdowson Member - All Emails Posts: 1,054

    Ah, the note is back. So here's an answer I prepared earlier...

    How can I retrieve the correct path for the file object in the IRP_MJ_SET_INFORMATION post callback for a FileRenameInformation.

     
    On MUP/RDR you cannot. Once a file object has been renamed the ONLY operations that work on it are close and cleanup (or that was the case last time I went there)
     

    Why does FltGetTunneledName return the original name for renames on \Device\Mup

     
    Pass. but IMO its about 30 years too late to still be worrying about name tunnelling. The apps will have stopped working of have been ported. Of course I'll walk in to a bug later today which proves me wrong
     

    Why does FltGetFileNameInformation always return the original name in the post-operation of a file rename.

     
    See above
     

    If i retrieve the name in the pre-operation callback and the post-operation callback succeedes, is the name still valid?

     
    I wouldn't bet on it. My general rule of thumb over the network, particularly with respect to 'filesystem' (as opposed to 'data') operations is that you can never rely on anything (for insyance include the rule that "you only ever get one StreamContext for any stream" just isn't true.
     
    In this case in particular you are totally dependant on the remote file system which may or may not allow any other person out there to rename the file again after your rename has worked. And I would't even assume that MUP/RDR is holding a HANDLE on the file on the server at this stage.

  • andreiandrei Member Posts: 4

    On an actual network it happened on an SMB share?
    Notice that the issue occurs on HGFS in your debug output, but not on
    SMB shares

    Yes, it also happened over an SMB share. It was the same behavior as with HGFS

    Pass. but IMO its about 30 years too late to still be worrying about name tunnelling. The apps will have stopped working of have been ported. Of course I'll walk in to a bug later today which proves me wrong

    I agree, but what bugs me is that FltGetTunneledName gives me the wrong name in the post callback (and so does FGFNI, since FGTN internally calls FGFNI). The only API that gives me the new name in the post callback is FGDFNI, but afaik this is dangerous to call in a post callback, because it requires the "RootDirectory" parameter. In a post callback we might be in an arbitrary context , and the RootDirectory could be a user-mode handle. I actually encountered a bugcheck with driver verifier enabled because FGDFNI was trying to reference a user-mode handle in the context of a system thread (where the I/O was completed).

    The strategy I currently use is to check if in the post callback we are in the context of the I/O requestor. If so, I call FGDFNI, else, I use the name returned by FGDFNI in the pre-callback. Do you see any potential issues with this approach?

    In this case in particular you are totally dependant on the remote file system which may or may not allow any other person out there to rename the file again after your rename has worked. And I would't even assume that MUP/RDR is holding a HANDLE on the file on the server at this stage.

    I don't care if the file was immediately renamed again by some client. All i really care about is if the rename was succesful and what was the final destination normalized name.

    Thank you for your time.

  • rod_widdowsonrod_widdowson Member - All Emails Posts: 1,054

    I have little succour beyond saying that I have never found reason to doubt that FGDFNI returns the correct speculative name in pre.

    In a post callback we might be in an arbitrary context

    I tend to the brute force and ignorance approache to these issues if I'm outside the IO paths and say FLT_PREOP_SYNCRHONIZE. For reads and writes (expecially to a local disk) I'll pull every trick possible to not get in the way of completion

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
Writing WDF Drivers 21 Oct 2019 OSR Seminar Space & ONLINE
Internals & Software Drivers 18 Nov 2019 Dulles, VA
Kernel Debugging 30 Mar 2020 OSR Seminar Space
Developing Minifilters 27 Apr 2020 OSR Seminar Space & ONLINE