FltGetDestinationNameInformation(), IRP_MJ_SET_INFORMATION and LanManRedirector: a recipe for disast

Hi list,

I have recently been struggling with deciphering the new filename for
a renamed file in my minifilter driver. My previous travails are
documented here:

http://www.osronline.com/showThread.CFM?link=173932

To recap my goal: when a user does something like this:

ren \myserver\myshare\myfile.txt yourfile.txt

I want to be able to determine that the file’s new name is
“\myserver\myshare\yourfile.txt”. For the record, I only care about
network shares, and my test/debug machines are all fully up-to-date
with their service packs and hotfixes.

I came up with two approaches:

  1. Call FltGetDestinationFileNameInformation in the
    SET_INFORMATION post-op handler
  2. Call FltGetDestinationFileNameInformation in the pre-op
    handler and double check the name in the post-op handler using
    FltGetTunneledName

Approach (1) is the simpler of the two, since I don’t need the name in
the pre-op handler. This works just fine for files on a local NTFS
partition, but not for a LanManRedirector share on XP – in this case
FltGetDestinationFileNameInformation fails with
STATUS_FLT_INVALID_NAME_REQUEST.

By means of some dissassembly of the
FltGetDestinationFileNameInformation code I was able to determine that
the function call fails because an internal call to IoGetTopLevelIrp
indicates that the IRP is part of a recursive request, and hence it is
not safe to make further queries of the filesystem since such a query
may lead to deadlocks. Unfortunately, this fact also scuppers
approach (2), since FltGetTunneledName fails for the same reason. As
such, I’m left with one final approach that I can think of:

  1. Call FltGetDestinationFileNameInformation in the pre-op
    handler (at this point IoGetTopLevelIrp says the request isn’t
    recursive), and hope that nothing changes due to filesystem tunneling

Of course, approach (3) is rather unpalatable since it flies directly
in the face of the MSDN documentation for
FltGetDestinationFileNameInformation – surely the kind of thing the
assiduous developer does only at her peril !

So, after all this investigation and head/wall interface events, I
have the following questions:

i) Can anyone suggest a safe, preferably MS-sanctified, method of
determining a renamed file’s new name on a LanMan share on XP ?
ii) Can anyone tell me whether filesystem tunneling is an issue on
LanMan shares ? Could I ignore it in this special case, making
approach (3) safe ?

Best regards,
Tom

NB. I note that on Vista I don’t have this issue with
FltGetDestinationFileNameInformation. On Vista, IoGetTopLevelIrp
indicates the post-rename is not part of a recursive call and hence
the filesystem query calls succeed. I assume this is due to the
re-architecture of LanManRedirector into Mup – and indeed, IrpTracker
shows me two separate calls on Vista (FltMgr -> Mup; Mup-> mrxsmb),
whereas it shows me only one on XP (FltMgr->LanManRedirector).

Tom Parkin
www.thhp.org.uk
The worst moment for the atheist is when he is really thankful and has
nobody to thank /Rossetti/

Tom,

i) Can anyone suggest a safe, preferably MS-sanctified, method of determining a renamed file’s new name on a LanMan share on XP ?

Unfortunately no. Do you absolutely need the destination name to accomplish what you are trying to do?

ii) Can anyone tell me whether filesystem tunneling is an issue on LanMan shares ? Could I ignore it in this special case, making approach (3) safe ?

You could perform a quick test by setting a short name, deleting the file and then recreating it using the short name. Check if it gets the original long name.

Scott

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Tom Parkin
Sent: Monday, January 18, 2010 7:39 AM
To: Windows File Systems Devs Interest List
Subject: [ntfsd] FltGetDestinationNameInformation(), IRP_MJ_SET_INFORMATION and LanManRedirector: a recipe for disaster ?

Hi list,

I have recently been struggling with deciphering the new filename for a renamed file in my minifilter driver. My previous travails are documented here:

http://www.osronline.com/showThread.CFM?link=173932

To recap my goal: when a user does something like this:

ren \myserver\myshare\myfile.txt yourfile.txt

I want to be able to determine that the file’s new name is “\myserver\myshare\yourfile.txt”. For the record, I only care about network shares, and my test/debug machines are all fully up-to-date with their service packs and hotfixes.

I came up with two approaches:

  1. Call FltGetDestinationFileNameInformation in the SET_INFORMATION post-op handler
  2. Call FltGetDestinationFileNameInformation in the pre-op handler and double check the name in the post-op handler using FltGetTunneledName

Approach (1) is the simpler of the two, since I don’t need the name in the pre-op handler. This works just fine for files on a local NTFS partition, but not for a LanManRedirector share on XP – in this case FltGetDestinationFileNameInformation fails with STATUS_FLT_INVALID_NAME_REQUEST.

By means of some dissassembly of the
FltGetDestinationFileNameInformation code I was able to determine that the function call fails because an internal call to IoGetTopLevelIrp indicates that the IRP is part of a recursive request, and hence it is not safe to make further queries of the filesystem since such a query may lead to deadlocks. Unfortunately, this fact also scuppers approach (2), since FltGetTunneledName fails for the same reason. As such, I’m left with one final approach that I can think of:

  1. Call FltGetDestinationFileNameInformation in the pre-op handler (at this point IoGetTopLevelIrp says the request isn’t recursive), and hope that nothing changes due to filesystem tunneling

Of course, approach (3) is rather unpalatable since it flies directly in the face of the MSDN documentation for FltGetDestinationFileNameInformation – surely the kind of thing the assiduous developer does only at her peril !

So, after all this investigation and head/wall interface events, I have the following questions:

i) Can anyone suggest a safe, preferably MS-sanctified, method of determining a renamed file’s new name on a LanMan share on XP ?
ii) Can anyone tell me whether filesystem tunneling is an issue on LanMan shares ? Could I ignore it in this special case, making approach (3) safe ?

Best regards,
Tom

NB. I note that on Vista I don’t have this issue with FltGetDestinationFileNameInformation. On Vista, IoGetTopLevelIrp indicates the post-rename is not part of a recursive call and hence the filesystem query calls succeed. I assume this is due to the re-architecture of LanManRedirector into Mup – and indeed, IrpTracker shows me two separate calls on Vista (FltMgr -> Mup; Mup-> mrxsmb), whereas it shows me only one on XP (FltMgr->LanManRedirector).

Tom Parkin
www.thhp.org.uk
The worst moment for the atheist is when he is really thankful and has nobody to thank /Rossetti/


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars (including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Hi Scott,

I am very confused by the TopLevelIrp thing that OP has mentioned. Why and
how is the top level IRP component non-NULL for a rename request?
Moreover, he mentions that in the PreOp callback the TopLevelIrp is NULL
(and that is why he is able to query the name in PreSetInfo).

What’s the scenario that could lead to a situation in which the TopLevelIrp
component is NULL in PreOp and non-NULL in PostOp?

Regards,
Ayush Gupta
AI Consulting

File systems set the top level IRP field during processing to detect re-entrant behavior.

Thus, if a file system sets the top level IRP, completes the request and clears the top level IRP, it will be SET in the post-op routine. This isn’t a bug in the underlying FSD, it’s just an artifact of the implementation. However, it DOES mean that if you issue another call back to the FSD, the top level IRP field will still be set on entry and that will confuse the underlying FSD.

When you layer file systems, or when you build “disk in a file” systems, you run into the top level IRP issue as well. What I usually do is save the old top level IRP value, issue the request, and then restore the top level IRP value. There are potential issues here, but generally you won’t run into them because you have a clearly defined ordering of operations and that avoids some of the annoyances (e.g., deadlocks.)

In the OPs case (where he’s trying to check for the rename) he’s just observing differences in implementations across versions.

With respect to the “you don’t get the right name back from LanManager” the answer to this is “it creates a potential attack vector for various security attacks.” For example, you can create a potentially infected file under a benign name and then rename it. The AV product could then find the OLD name and skip the security check. There are more subtle approaches here as well.

For the OP: if you can install a server side component, you can always use an FSCTL tunnel, which works because unknown FSCTL operations are sent to the server. Since the SERVER can “do this right” you can rely upon it to achieve this. We used to do this to obtain the file ID of the file - we built an entire shared fibre channel disk subsystem, in which CIFS was used as the control layer and the actual blocks of the file were directly accessed from the client. One of the things we HAD to know was “what’s the real file underlying this” - and we used the FSCTL tunneling trick to get back the real FID instead of the imaginary number that CIFS returns.

However, this doesn’t work if you can’t install a server side component. I’ve complained about the potential issues around this for years, but the bottom line is that making this “correct” is very expensive (think about the “two clients” case in which one renames the file but the query is done on the other client.)

Tony
OSR

Hi Scott,

Thanks for the answers !

2010/1/18 Scott Brender :
> ? ?i) ?Can anyone suggest a safe, preferably MS-sanctified, method of determining a renamed file’s new name on a LanMan share on XP ?
>
> ? ? ? ?Unfortunately no. Do you absolutely need the destination name to accomplish what you are trying to do?
>

Sadly I think I do, yes. But thanks for the reality check – it’s too
easy to get bogged down in a problem like this and to miss the wood
for the trees.

> ? ?ii) Can anyone tell me whether filesystem tunneling is an issue on LanMan shares ? ?Could I ignore it in this special case, making approach (3) safe ?
>
> ? ? ? ?You could perform a quick test by setting a short name, deleting the file and then recreating it using the short name. Check if it gets the original long name.
>

Indeed, and my test suggests that the original file name is not tunneled:

echo x > “\nova\test\this is my file.txt”
del “\nova\test\this is my file.txt”
echo x > \nova\test\thisis~1.txt
dir \nova\test\this*.txt
10/09/2010 09:48 4 thisis~1.txt

So the new file doesn’t get the original long name; hence no tunneling
for this particular CIFS server. That’s an encouraging start, and
(perhaps after testing a few more implementations) might imply that I
don’t need to worry about tunneling for this use case.

Best regards,
Tom

Tom Parkin
www.thhp.org.uk
The worst moment for the atheist is when he is really thankful and has
nobody to thank /Rossetti/

Hi Tony,

Many thanks for the insight and discussion.

2010/1/19 Tony Mason :
> For the OP: if you can install a server side component, you can always use an FSCTL tunnel, which works because unknown FSCTL operations are sent to the server. ?Since the SERVER can “do this right” you can rely upon it to achieve this. ?We used to do this to obtain the file ID of the file - we built an entire shared fibre channel disk subsystem, in which CIFS was used as the control layer and the actual blocks of the file were directly accessed from the client. ?One of the things we HAD to know was “what’s the real file underlying this” - and we used the FSCTL tunneling trick to get back the real FID instead of the imaginary number that CIFS returns.
>
> However, this doesn’t work if you can’t install a server side component. ? I’ve complained about the potential issues around this for years, but the bottom line is that making this “correct” is very expensive (think about the “two clients” case in which one renames the file but the query is done on the other client.)
>

Ugh, yes, things undoubtedly get more complicated for the two client
scenario – although I suppose that’s the price you start having to
pay when you have multiple hosts accessing the same filesystem over
(potentially) high-latency network links. To some extent this is
orthogonal to the issue I’m having: if one client did the rename and
the other the name query then the query would be decoupled from the
rename operation and my specific problem would go away (that is:
FltGetDestinationFileNameInformation() in post-rename fails). Instead,
you’re just left with a good old race condition around the order that
the SMB messages hit the server and got processed.

However, I’d be quite happy to make things “work” for the simple,
single-client scenario at present ! Your suggestion about the FSCTL
tunnel is a good one, and that’s something that I will take a look at
going forward.

All the best,
Tom

Tom Parkin
www.thhp.org.uk
The worst moment for the atheist is when he is really thankful and has
nobody to thank /Rossetti/