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 >