[PATCH] smbd: add reparse points at symlinks

Jacob Holtom jacob at et.byu.edu
Wed Dec 2 18:28:49 UTC 2015


with follow symlinks and wide links enabled, they normally would just 
see it as a continuation of the current path rather than a point to 
another location

Sadly, the documentation on what the windows symlink filter driver does 
is rather lacking, so the best I can do is make informed assumptions.

Now when they connect and encounter a reparse point with the 
IO_REPARSE_TAG_SYMLINK they will interpret it as the start of a new path 
and therefore re-evaluate everything (probably a new tree_connect at 
that point) rather than inheriting everything above it.  This is mostly 
useful in the case of wide links, so that instead of inheriting the 
original filesystems attributes, it goes and finds those of the target 
filesystems.

Thanks!
Jacob

On 11/30/2015 12:32 PM, Jeremy Allison wrote:
> On Mon, Nov 30, 2015 at 11:42:49AM -0700, Jacob Holtom wrote:
>> Hi,
>>
>> This patch adds a reparse point at symlinks, with the correct
>> accompanying tag as defined by microsoft.
>> this may be better implemented with a compile time option of
>> smb.conf flag, review appreciated
>
> Interesting patch Jacob, thanks !
>
> What do Windows clients do when they see an smbd symlink
> as a reparse point ?
>
>>  From 2175ed1fd6844eb5528b005f1694f68513746a99 Mon Sep 17 00:00:00 2001
>> From: Jacob Holtom <jacob at et.byu.edu>
>> Date: Mon, 30 Nov 2015 11:27:52 -0700
>> Subject: [PATCH] smbd: add reparse points at symlinks
>>
>> Signed-off-by: Jacob Holtom <jacob at et.byu.edu>
>> ---
>>   source3/include/ntioctl.h |  2 +-
>>   source3/smbd/dosmode.c    |  9 ++++++++-
>>   source3/smbd/trans2.c     | 15 ++++++++++++---
>>   3 files changed, 21 insertions(+), 5 deletions(-)
>>
>> diff --git a/source3/include/ntioctl.h b/source3/include/ntioctl.h
>> index f9e6dd9..850e85f 100644
>> --- a/source3/include/ntioctl.h
>> +++ b/source3/include/ntioctl.h
>> @@ -27,7 +27,7 @@
>>   #define IO_REPARSE_TAG_HSM           0xC0000004
>>   #define IO_REPARSE_TAG_SIS           0x80000007
>>   #define IO_REPARSE_TAG_DFS	     0x8000000A
>> -
>> +#define IO_REPARSE_TAG_SYMLINK       0xA000000C
>>   
>>   /* For FSCTL_GET_SHADOW_COPY_DATA ...*/
>>   typedef char SHADOW_COPY_LABEL[25];
>> diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
>> index 0f3eef0..e1e84ce 100644
>> --- a/source3/smbd/dosmode.c
>> +++ b/source3/smbd/dosmode.c
>> @@ -246,6 +246,8 @@ static uint32_t dos_mode_from_sbuf(connection_struct *conn,
>>   		result = FILE_ATTRIBUTE_DIRECTORY | (result & FILE_ATTRIBUTE_READONLY);
>>   
>>   	result |= set_link_read_only_flag(&smb_fname->st);
>> +        if(S_ISLNK(smb_fname->st.st_ex_mode))
>> +            result |= FILE_ATTRIBUTE_REPARSE_POINT;
>>   
>>   	dos_mode_debug_print(__func__, result);
>>   
>> @@ -364,6 +366,8 @@ static bool get_ea_dos_attribute(connection_struct *conn,
>>   	if (S_ISDIR(smb_fname->st.st_ex_mode)) {
>>   		dosattr |= FILE_ATTRIBUTE_DIRECTORY;
>>   	}
>> +        if(S_ISLNK(smb_fname->st.st_ex_mode))
>> +                dosattr |= FILE_ATTRIBUTE_REPARSE_POINT;
>>   	/* FILE_ATTRIBUTE_SPARSE is valid on get but not on set. */
>>   	*pattr = (uint32_t)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE));
>>   
>> @@ -633,7 +637,10 @@ uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname)
>>   	if (result == 0) {
>>   		result = FILE_ATTRIBUTE_NORMAL;
>>   	}
>> -
>> +        //Add in reparse point if symlink
>> +        if(S_ISLNK(smb_fname->st.st_ex_mode))
>> +            result |= FILE_ATTRIBUTE_REPARSE_POINT;
>> +        //End Additions
>>   	result = filter_mode_by_protocol(result);
>>   
>>   	dos_mode_debug_print(__func__, result);
>> diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
>> index 11c97e8..fa3eba5 100644
>> --- a/source3/smbd/trans2.c
>> +++ b/source3/smbd/trans2.c
>> @@ -1864,7 +1864,10 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
>>   		SIVAL(p,0,mode); p += 4;
>>   		q = p; p += 4; /* q is placeholder for name length. */
>>   		if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
>> -			SIVAL(p, 0, IO_REPARSE_TAG_DFS);
>> +                        if(S_ISLNK(mode))
>> +                            SIVAL(p,0,IO_REPARSE_TAG_SYMLINK);
>> +                        else
>> +                            SIVAL(p, 0, IO_REPARSE_TAG_DFS);
>>   		} else {
>>   			unsigned int ea_size = estimate_ea_size(conn, NULL,
>>   								smb_fname);
>> @@ -2058,7 +2061,10 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
>>   		SIVAL(p,0,mode); p += 4;
>>   		q = p; p += 4; /* q is placeholder for name length. */
>>   		if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
>> -			SIVAL(p, 0, IO_REPARSE_TAG_DFS);
>> +                        if(S_ISLNK(mode))
>> +                            SIVAL(p,0,IO_REPARSE_TAG_SYMLINK);
>> +                        else
>> +                            SIVAL(p, 0, IO_REPARSE_TAG_DFS);
>>   		} else {
>>   			unsigned int ea_size = estimate_ea_size(conn, NULL,
>>   								smb_fname);
>> @@ -2109,7 +2115,10 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
>>   		SIVAL(p,0,mode); p += 4;
>>   		q = p; p += 4; /* q is placeholder for name length */
>>   		if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
>> -			SIVAL(p, 0, IO_REPARSE_TAG_DFS);
>> +			if(S_ISLNK(mode))
>> +                            SIVAL(p, 0, IO_REPARSE_TAG_SYMLINK);
>> +                        else
>> +                            SIVAL(p, 0, IO_REPARSE_TAG_DFS);
>>   		} else if (readdir_attr_data &&
>>   			   readdir_attr_data->type == RDATTR_AAPL) {
>>   			/*
>> -- 
>> 2.6.2
>>
>




More information about the samba-technical mailing list