lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20241224131859.3457-1-pali@kernel.org>
Date: Tue, 24 Dec 2024 14:18:59 +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: [PATCH v2] cifs: Fix getting reparse points from servers without EAs support

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

Powered by Openwall GNU/*/Linux Powered by OpenVZ