Re: [PATCH v2] cifs: Fix getting reparse points from servers without EAs support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello, do you have any comments for this fix?

On Tuesday 24 December 2024 14:18:59 Pali Rohár wrote:
> If SMB server does not support EAs then for SMB2_OP_QUERY_WSL_EA request it
> returns STATUS_EAS_NOT_SUPPORTED. Function smb2_compound_op() translates
> STATUS_EAS_NOT_SUPPORTED to -EOPNOTSUPP which cause failure during calling
> lstat() syscall from userspace on any reparse point, including Native SMB
> symlink (which does not use any EAs).
> 
> If SMB server does not support to attach both EAs and Reparse Point to path
> at the same time then same error STATUS_EAS_NOT_SUPPORTED is returned. This
> is the case for Windows 8 / Windows Server 2012. It is known limitation of
> NTFS driver in those older Windows versions.
> 
> Since commit ea41367b2a60 ("smb: client: introduce SMB2_OP_QUERY_WSL_EA")
> Linux SMB client always ask for EAs on detected reparse point paths due to
> support of WSL EAs. But this commit broke reparse point support for all
> older Windows SMB servers which do not have support for WSL and WSL EAs.
> 
> Avoid this problem by retrying the request without SMB2_OP_QUERY_WSL_EA
> when it fails on -EOPNOTSUPP error.
> 
> This should fix broken support for all special files (symlink, fifo,
> socket, block and char) for SMB server which do not support EAs at all and
> for SMB server which do not allow to attach both EAs and Reparse Point at
> the same time.
> 
> Fixes: ea41367b2a60 ("smb: client: introduce SMB2_OP_QUERY_WSL_EA")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Pali Rohár <pali@xxxxxxxxxx>
> ---
>  fs/smb/client/smb2inode.c | 38 +++++++++++++++++++++++++++++++++++++-
>  1 file changed, 37 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
> index e8bb3f8b53f1..58276434e47b 100644
> --- a/fs/smb/client/smb2inode.c
> +++ b/fs/smb/client/smb2inode.c
> @@ -875,6 +875,7 @@ int smb2_query_path_info(const unsigned int xid,
>  	bool islink;
>  	int i, num_cmds = 0;
>  	int rc, rc2;
> +	bool skip_wsl_ea;
>  
>  	data->adjust_tz = false;
>  	data->reparse_point = false;
> @@ -943,7 +944,13 @@ int smb2_query_path_info(const unsigned int xid,
>  		if (rc || !data->reparse_point)
>  			goto out;
>  
> -		if (!tcon->posix_extensions)
> +		skip_wsl_ea = false;
> +retry_cmd:
> +		/*
> +		 * Skip SMB2_OP_QUERY_WSL_EA if using POSIX extensions or
> +		 * retrying request with explicitly skipping for WSL EAs.
> +		 */
> +		if (!tcon->posix_extensions && !skip_wsl_ea)
>  			cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA;
>  		/*
>  		 * Skip SMB2_OP_GET_REPARSE if symlink already parsed in create
> @@ -961,6 +968,35 @@ int smb2_query_path_info(const unsigned int xid,
>  		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
>  				      &oparms, in_iov, cmds, num_cmds,
>  				      cfile, NULL, NULL, NULL);
> +		if (rc == -EOPNOTSUPP && !tcon->posix_extensions && !skip_wsl_ea) {
> +			/*
> +			 * Older Windows versions do not allow to set both EAs
> +			 * and Reparse Point as the same time. This is known
> +			 * limitation of older NTFS driver and it was fixed in
> +			 * Windows 10. Trying to query EAs on file which has
> +			 * Reparse Point set ends with STATUS_EAS_NOT_SUPPORTED
> +			 * error, even when server filesystem supports EAs.
> +			 * This error is translated to errno -EOPNOTSUPP.
> +			 * So in this case retry the request again without EAs.
> +			 */
> +			skip_wsl_ea = true;
> +			num_cmds = 1;
> +			goto retry_cmd;
> +		}
> +		if (rc == 0 && skip_wsl_ea &&
> +		    (data->reparse.tag == IO_REPARSE_TAG_LX_CHR ||
> +		     data->reparse.tag == IO_REPARSE_TAG_LX_BLK)) {
> +			/*
> +			 * WSL CHR and BLK reparse points store major and minor
> +			 * device numbers in EAs (instead of reparse point buffer,
> +			 * like it is for WSL symlink or NFS reparse point types).
> +			 * Therefore with skipped EAs it is not possible to finish
> +			 * query of these files. So change error back to the
> +			 * original -EOPNOTSUPP.
> +			 */
> +			rc = -EOPNOTSUPP;
> +		}
> +
>  		if (data->reparse.tag == IO_REPARSE_TAG_SYMLINK && !rc) {
>  			bool directory = le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY;
>  			rc = smb2_fix_symlink_target_type(&data->symlink_target, directory, cifs_sb);
> -- 
> 2.20.1
> 




[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux