[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20250107202416.6z4bw5wdgjnymkjg@pali>
Date: Tue, 7 Jan 2025 21:24:16 +0100
From: Pali Rohár <pali@...nel.org>
To: Steve French <sfrench@...ba.org>, Paulo Alcantara <pc@...guebit.com>,
Ronnie Sahlberg <ronniesahlberg@...il.com>
Cc: linux-cifs@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v2] cifs: Fix getting reparse points from servers without
EAs support
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@...r.kernel.org
> Signed-off-by: Pali Rohár <pali@...nel.org>
> ---
> 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
>
Powered by blists - more mailing lists