[Patch] dosmode: Compare block devices to detect reparse points

Noel Power nopower at suse.com
Tue Feb 12 19:31:55 UTC 2019


Hi,

First thing I noticed is that there was no patch, I attach it here for
reference. Also apologies for the delay in getting back to you, I did
want to try this out and I only got a chance to do that just recently.

On 05/02/2019 19:50, James Ashdown via samba-technical wrote:
>
> On 1/30/19 16:11, Daniel Fussell via samba-technical wrote:
>
>> On 1/30/19 12:53 AM, Noel Power via samba-technical wrote:
>>> On 28/01/2019 23:40, James Ashdown wrote:
>>>> I'm attaching a revision of the patch that makes use of your idea to
>>>> re-use the parent directory stat on a FIND operation. Turns out that
>>>> it works beautifully, no additional stat calls needed there.
>>>>
>>>> However, I encountered a snag when I implemented just that. It seems
>>>> that when a Windows 10 File Explorer client opens a
>>>> reparsepoint-marked directory sends a CREATE request targeting that
>>>> directory,
>>> how do you trigger the CREATE request?
>> It is essentially open existing file/directory, or create and open
>> non-existing file/directory.
>>>> the client overwrites its reparsepoint state for that directory. In
>>>> effect, if you enter a directory and then quickly leave and re-enter
>>>> it, write and copy operations "forget" that there was ever a
>>>> reparsepoint file attribute set.
>>> so you mean if you click into a dir mountpoint and quickly leave (say
>>> clicking the parent) and then click back again ? Then try a copy and it
>>> will revert back to (in my example from earlier in the thread) using
>>> the
>>> quota associated with the parent dir share ?
>> Exactly
>>>> To fix that, I mimicked the CREATE flag that Windows File Server
>>>> returns. This is not in the file attributes bit field, but has the
>>>> effect of preserving the set FILE_ATTRIBUTE_REPARSEPOINT returned in
>>>> the FIND response. Detecting the mountpoint here requires an
>>>> additional stat for each CREATE that targets a directory.
>>> Do you have before and after network traces (would help to point out
>>> the
>>> relevant packets in each for comparison) At least for me I haven't
>>> looked at this in a while and could do with a big fat finger pointing
>>> things out :-)
>> Yes, we've been using wireshark to compare our patch's packets against
>> an MS server with a similar directory structure so we can better match
>> the behavior.  We may not have saved the packet traces, but we can
>> certainly generate them again if you want to see them.
I see now the flag that you mean, this is the one I mentioned in the
comments on my original patch. I don't think that this solves the
problem though, at least testing with your patch I can still get it to
misbehave in the same way (I am using a windows 8.1 client though). I
did think that it seemed a little harder to make it break, in other
words I think the patch improves things but doesn't fix it.
>>
>> We haven't spent a lot of time looking for other operations that might
>> need to return the same flags.  CLOSE
>> is the obvious additional candidate, but in our limited testing, we
>> never saw the file attributes go across the wire.  That doesn't mean it
>> would never happen though, so we might have to check that out.
>>> Also did you find any documentation around the flag you are
>>> setting ? I seem to recall finding precious little about the associated
>>> flags and when/how to use them when I last looked.
>>  From MS-SMB2 (and Jeremy, feel free to jump in and correct me if I'm
>> wrong here):
>>
>> The SMB2_CREATE_FLAG_REPARSEPOINT flag is documented at
>> https://msdn.microsoft.com/en-us/library/cc246512.aspx (and now that I
>> re-read the "Flags" definition, we may have to modify the patch such
>> that this flag is only set if SMB3.x was negotiated.)
>>
>> The FILE_ATTRIBUTE_REPARSE_POINT flag is documented at
>> https://msdn.microsoft.com/en-us/library/cc232110.aspx

Yes have seen those, not alot of information though on how they are to
be used/interpreted.

For example I did a little bit of testing with some windows hosted
reparsepoint files by poking at them with a modified smbclient and the
results are a little strange and to me inconsistent


The files used for testing were,

1) A DFS namespace

2) directory symlink

3) directory junction

4) a mountpoint to a share created by Disk Manager

Windows (windows 2012 server)  behaviour

SMB2 response to SMB2_FIND_ID_BOTH_DIRECTORY_INFO request

1) a (nested) DFS namespace in an existing share, has entry is marked
with FILE_ATTRIBUTE_REPARSE_POINT
2) a symlink created with mklink /D (directory) also has entry is marked
with FILE_ATTRIBUTE_REPARSE_POINT
3) a symlink created with mklink /J (directory Junction)) also has entry
is marked with FILE_ATTRIBUTE_REPARSE_POINT
4) a mount point created by Disk manager  (from an initially unassigned
partition) also has entry is marked with FILE_ATTRIBUTE_REPARSE_POINT

SMB2 response to Create (normal create options e.g.
FILE_OPEN_REPARSE_POINT is NOT set)

1) a (nested) DFS namespace in an existing share, Response flags are
*not* set, file attributes don't have FILE_ATTRIBUTE_REPARSE_POINT set.
2) a symlink created with mklink /D (directory),
NT_STATUS_STOPPED_ON_SYMLINK
3) a symlink created with mklink /J (directory Junction), Response flags
contain SMB2_CREATE_FLAG_REPARSEPOINT, file attributes *don't* have
FILE_ATTRIBUTE_REPARSE_POINT set.
4) a mount point created by Disk manager, Response flags contain
SMB2_CREATE_FLAG_REPARSEPOINT, file attributes *don't* have
FILE_ATTRIBUTE_REPARSE_POINT set.

SMB2 response to Create (request has creation options with
FILE_OPEN_REPARSE_POINT set)
1) a (nested) DFS namespace in an existing share, Response flags are NOT
set, file attributes *don't* have FILE_ATTRIBUTE_REPARSE_POINT set.
2) a symlink created with mklink /D (directory), Response flags are NOT
set, file attributes *have* FILE_ATTRIBUTE_REPARSE_POINT set
3) a symlink created with mklink /J (directory Junction), Response are
NOT set, file attributes *have* FILE_ATTRIBUTE_REPARSE_POINT set.
4) a mount point created by Disk manager, Response flags are NOT set,
file attributes *have* FILE_ATTRIBUTE_REPARSE_POINT set.

SMB2 response to FSCTL_GET_REPARSE_POINT_FILE
1) a (nested) DFS namespace in an existing share,
NT_STATUS_NOT_A_REPARSE_POINT
2) a symlink created with mklink /D (directory),  REPARSE_DATA_BUFFER
data returned
3) a symlink created with mklink /J (directory Junction),
REPARSE_DATA_BUFFER data returned
4) a mount point created by Disk manager, REPARSE_DATA_BUFFER data returned

Further examination showed mount point and mklink /J (directory Juntion)
link are actually the same thing, both have reparse tag with value
0xA0000003, they differ only in the data in the buffer, in the case of
the 'directory junction' an actual path is stored and in the case of the
mount point (created from disk manager) it is a GUID

What about the response flags, documentation says
"If the server implements the SMB 3.x dialect family, this field MUST be
constructed using the following value. Otherwise, this field MUST NOT be
used and MUST be reserved"

However the values observed above are consistent with a client
negotiating SMB2_02, SMB2_2FF and SMB3 protocols

Also of course the closest windows setup (e.g. windows server with a
nested mountpoint (or directory junction) where the nested directory
actually points to a different partition with different quotas I could
not get it it misbehave (while switching quickly between parent and
nested directories)

Some observations, when the windows client fails to write a file into a
nested mountpoint (on a hacked up linux server patched with mountpoint
support) I see that the error message mentions the parent share
directory (see CiientHasWrongQuota.png) Note: in this case a wireshark
trace actually shows the client has just made a
FileFsFullSizeInformation for the correct directory (nestedFS in this
case). If the correct quotas were being honoured then
CorrectQuotError.png would be shown if the quota was exceeded.

In the windows only case (where nestedFS is hosted on a windows server)
I noticed a couple of other things, before the FileFsFullSizeInformation
there is always a SMB2 create request for the nestedFS with create
options(0x200021) & disposition Create (e.g. if file exists fail, else
create it) The response always errors out with
NT_STATUS_OBJECT_NAME_COLLISION. Also I see SMB2 GetInfo
FileFsVolumeInformation responses set 'Reparse Points' as being
supported in the file system attributes (quickly hardcoding this into a
linux server didn't help though)

>>
>> Furthermore, MS-FSCC section 2.1.2.1 paragraph 3, says "The following
>> reparse tags, with the exception of IO_REPARSE_TAG_SYMLINK, are
>> processed on the server and are not processed by a client after
>> transmission over the wire.  Clients SHOULD treat associated reparse
>> data as opaque data."  I've probably quoted this before, and I don't
>> mean to be a broken record, but I paid an awful price finding it again
>> and again in all the wrong places.
>>
>>  From those three references, I gather that the flags clue the client
>> into existence of a reparse point.  While it is true that a client could
>> potentially issue an FSCTL or IOCTL with the intent of setting or
>> reading a reparse point, the FSCTL and IOCTL's are implementation
>> specific.  So supporting some controls and not others seems reasonable.
>>
>> Furthermore, regarding Jeremy's aforementioned
>> FSCTL_REPARSE_POINT-implicit-promise-is-can-of-worms concern, MS-SMB2
>> 3.3.5.15 paragraph 12 says "The server SHOULD fail the request with
>> STATUS_NOT_SUPPORTED when an FSCTL is not allowed on the server, and
>> SHOULD fail the request with STATUS_INVALID_DEVICE_REQUEST when the
>> FSCTL is allowed, but is not supported on the file system on which the
>> file or directory handle specified by the FSCTL exists, as specified in
>> [MS-FSCC] section 2.2."
>>
>> As I understand it, fsutil requires admin privileges in the first place,
>> so I think it perfectly reasonable to reject a FSCTL_SET_REPARSE_POINT
>> call with STATUS_NOT_SUPPORTED because it doesn't mean anything in this
>> context.  And yeah, FSCTL_GET_REPARSE_POINT might be callable by a
>> process with Backup privileges, so maybe STATUS_NOT_SUPPORTED isn't the
>> best return for that, or maybe it is.  Maybe there is another error we
>> can return like STATUS_CONTINUE or
>> STATUS_MOVE_ALONG_NOTHING_TO_SEE_HERE.
>>
>> But besides Backup and Admin privileged processes, it looks to me like
>> everyone else would be denied reading or writing a reparse tag and the
>> same with any application they might be running.  So restating the prior
>> question, would it be reasonable to make reparse mountpoint
>> detection/flagging a config option, and  revisit changing the default at
>> some future time?
>>
> What remains to be done for this patch to be considered for upstream
> integration?
First of all Jeremy needs to be convinced as he has some concerns btw I
do agree with your observations above about FSCTL_SET/GET etc. and have
expressed that previously.

Secondly I think certainly this needs to be controlled via config (see
npower-mountpoint.diff, this is a scaled down version, just targetting
mountpoint support, my version is a little different from yours, for
simplicity and also due to 'experimental' nature I'm trying not to touch
existing structures, not trying to optimise by passing down parent 
smb_filename struct etc.)

Thirdly I think we need to get to the point where at least the correct
quotas are actually used, despite looking hard at the network traces I
didn't yet see where we go wrong or what we might be missing that
triggers the correct behaviour.


Noel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Detect-volume-mountpoint-reparsepoints-for-FIND-and-.patch
Type: text/x-patch
Size: 9601 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20190212/762d49f3/0001-Detect-volume-mountpoint-reparsepoints-for-FIND-and--0001.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ClientHasWrongQuota.png
Type: image/png
Size: 153621 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20190212/762d49f3/ClientHasWrongQuota-0001.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: CorrectQuotError.png
Type: image/png
Size: 173444 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20190212/762d49f3/CorrectQuotError-0001.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: npower-mountpoint.diff
Type: text/x-patch
Size: 9885 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20190212/762d49f3/npower-mountpoint-0001.bin>


More information about the samba-technical mailing list