* [PATCH 2/4] cifs: Simplify reparse point check in cifs_query_path_info() function
2024-12-27 17:38 [PATCH 1/4] cifs: Remove symlink member from cifs_open_info_data union Pali Rohár
@ 2024-12-27 17:38 ` Pali Rohár
2024-12-27 17:38 ` [PATCH 3/4] cifs: Validate EAs for WSL reparse points Pali Rohár
2024-12-27 17:38 ` [PATCH 4/4] cifs: Fix querying of WSL CHR and BLK reparse points over SMB1 Pali Rohár
2 siblings, 0 replies; 4+ messages in thread
From: Pali Rohár @ 2024-12-27 17:38 UTC (permalink / raw)
To: Steve French, Paulo Alcantara; +Cc: linux-cifs, linux-kernel
For checking if path is reparse point and setting data->reparse_point
member, it is enough to check if ATTR_REPARSE is present.
It is not required to call CIFS_open() without OPEN_REPARSE_POINT and
checking for -EOPNOTSUPP error code.
Signed-off-by: Pali Rohár <pali@kernel.org>
---
fs/smb/client/smb1ops.c | 26 +-------------------------
1 file changed, 1 insertion(+), 25 deletions(-)
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index 73d4cc1534ff..3af3f64b0cba 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -564,32 +564,8 @@ static int cifs_query_path_info(const unsigned int xid,
}
if (!rc) {
- int tmprc;
- int oplock = 0;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
-
move_cifs_info_to_smb2(&data->fi, &fi);
-
- if (!(le32_to_cpu(fi.Attributes) & ATTR_REPARSE))
- return 0;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = FILE_READ_ATTRIBUTES,
- .create_options = cifs_create_options(cifs_sb, 0),
- .disposition = FILE_OPEN,
- .path = full_path,
- .fid = &fid,
- };
-
- /* Need to check if this is a symbolic link or not */
- tmprc = CIFS_open(xid, &oparms, &oplock, NULL);
- if (tmprc == -EOPNOTSUPP)
- data->reparse_point = true;
- else if (tmprc == 0)
- CIFSSMBClose(xid, tcon, fid.netfid);
+ data->reparse_point = le32_to_cpu(fi.Attributes) & ATTR_REPARSE;
}
return rc;
--
2.20.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 3/4] cifs: Validate EAs for WSL reparse points
2024-12-27 17:38 [PATCH 1/4] cifs: Remove symlink member from cifs_open_info_data union Pali Rohár
2024-12-27 17:38 ` [PATCH 2/4] cifs: Simplify reparse point check in cifs_query_path_info() function Pali Rohár
@ 2024-12-27 17:38 ` Pali Rohár
2024-12-27 17:38 ` [PATCH 4/4] cifs: Fix querying of WSL CHR and BLK reparse points over SMB1 Pali Rohár
2 siblings, 0 replies; 4+ messages in thread
From: Pali Rohár @ 2024-12-27 17:38 UTC (permalink / raw)
To: Steve French, Paulo Alcantara; +Cc: linux-cifs, linux-kernel
Major and minor numbers for char and block devices are mandatory for stat.
So check that the WSL EA $LXDEV is present for WSL CHR and BLK reparse
points.
WSL reparse point tag determinate type of the file. But file type is
present also in the WSL EA $LXMOD. So check that both file types are same.
Fixes: 78e26bec4d6d ("smb: client: parse uid, gid, mode and dev from WSL reparse points")
Signed-off-by: Pali Rohár <pali@kernel.org>
---
fs/smb/client/reparse.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index 9fe9dd71a6fa..9e40f5709c7f 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -1105,11 +1105,12 @@ struct reparse_data_buffer *smb2_get_reparse_point_buffer(const struct kvec *rsp
le32_to_cpu(io->OutputOffset));
}
-static void wsl_to_fattr(struct cifs_open_info_data *data,
+static bool wsl_to_fattr(struct cifs_open_info_data *data,
struct cifs_sb_info *cifs_sb,
u32 tag, struct cifs_fattr *fattr)
{
struct smb2_file_full_ea_info *ea;
+ bool have_xattr_dev = false;
u32 next = 0;
switch (tag) {
@@ -1152,13 +1153,24 @@ static void wsl_to_fattr(struct cifs_open_info_data *data,
fattr->cf_uid = wsl_make_kuid(cifs_sb, v);
else if (!strncmp(name, SMB2_WSL_XATTR_GID, nlen))
fattr->cf_gid = wsl_make_kgid(cifs_sb, v);
- else if (!strncmp(name, SMB2_WSL_XATTR_MODE, nlen))
+ else if (!strncmp(name, SMB2_WSL_XATTR_MODE, nlen)) {
+ /* File type in reparse point tag and in xattr mode must match. */
+ if (S_DT(fattr->cf_mode) != S_DT(le32_to_cpu(*(__le32 *)v)))
+ return false;
fattr->cf_mode = (umode_t)le32_to_cpu(*(__le32 *)v);
- else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen))
+ } else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen)) {
fattr->cf_rdev = reparse_mkdev(v);
+ have_xattr_dev = true;
+ }
} while (next);
out:
+
+ /* Major and minor numbers for char and block devices are mandatory. */
+ if (!have_xattr_dev && (tag == IO_REPARSE_TAG_LX_CHR || tag == IO_REPARSE_TAG_LX_BLK))
+ return false;
+
fattr->cf_dtype = S_DT(fattr->cf_mode);
+ return true;
}
static bool posix_reparse_to_fattr(struct cifs_sb_info *cifs_sb,
@@ -1221,7 +1233,9 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
case IO_REPARSE_TAG_AF_UNIX:
case IO_REPARSE_TAG_LX_CHR:
case IO_REPARSE_TAG_LX_BLK:
- wsl_to_fattr(data, cifs_sb, tag, fattr);
+ ok = wsl_to_fattr(data, cifs_sb, tag, fattr);
+ if (!ok)
+ return false;
break;
case IO_REPARSE_TAG_NFS:
ok = posix_reparse_to_fattr(cifs_sb, fattr, data);
--
2.20.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 4/4] cifs: Fix querying of WSL CHR and BLK reparse points over SMB1
2024-12-27 17:38 [PATCH 1/4] cifs: Remove symlink member from cifs_open_info_data union Pali Rohár
2024-12-27 17:38 ` [PATCH 2/4] cifs: Simplify reparse point check in cifs_query_path_info() function Pali Rohár
2024-12-27 17:38 ` [PATCH 3/4] cifs: Validate EAs for WSL reparse points Pali Rohár
@ 2024-12-27 17:38 ` Pali Rohár
2 siblings, 0 replies; 4+ messages in thread
From: Pali Rohár @ 2024-12-27 17:38 UTC (permalink / raw)
To: Steve French, Paulo Alcantara; +Cc: linux-cifs, linux-kernel
When reparse point in SMB1 query_path_info() callback was detected then
query also for EA $LXDEV. In this EA are stored device major and minor
numbers used by WSL CHR and BLK reparse points. Without major and minor
numbers, stat() syscall does not work for char and block devices.
Similar code is already in SMB2+ query_path_info() callback function.
Signed-off-by: Pali Rohár <pali@kernel.org>
---
fs/smb/client/smb1ops.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index 3af3f64b0cba..c52fc4c1557c 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -568,6 +568,42 @@ static int cifs_query_path_info(const unsigned int xid,
data->reparse_point = le32_to_cpu(fi.Attributes) & ATTR_REPARSE;
}
+#ifdef CONFIG_CIFS_XATTR
+ /*
+ * For WSL CHR and BLK reparse points it is required to fetch
+ * EA $LXDEV which contains major and minor device numbers.
+ */
+ if (!rc && data->reparse_point) {
+ struct smb2_file_full_ea_info *ea;
+
+ ea = (struct smb2_file_full_ea_info *)data->wsl.eas;
+ rc = CIFSSMBQAllEAs(xid, tcon, full_path, SMB2_WSL_XATTR_DEV,
+ &ea->ea_data[SMB2_WSL_XATTR_NAME_LEN + 1],
+ SMB2_WSL_XATTR_DEV_SIZE, cifs_sb);
+ if (rc == SMB2_WSL_XATTR_DEV_SIZE) {
+ ea->next_entry_offset = cpu_to_le32(0);
+ ea->flags = 0;
+ ea->ea_name_length = SMB2_WSL_XATTR_NAME_LEN;
+ ea->ea_value_length = cpu_to_le16(SMB2_WSL_XATTR_DEV_SIZE);
+ memcpy(&ea->ea_data[0], SMB2_WSL_XATTR_DEV, SMB2_WSL_XATTR_NAME_LEN + 1);
+ data->wsl.eas_len = sizeof(*ea) + SMB2_WSL_XATTR_NAME_LEN + 1 +
+ SMB2_WSL_XATTR_DEV_SIZE;
+ rc = 0;
+ } else if (rc >= 0) {
+ /* It is an error if EA $LXDEV has wrong size. */
+ rc = -EINVAL;
+ } else {
+ /*
+ * In all other cases ignore error if fetching
+ * of EA $LXDEV failed. It is needed only for
+ * WSL CHR and BLK reparse points and wsl_to_fattr()
+ * handle the case when EA is missing.
+ */
+ rc = 0;
+ }
+ }
+#endif
+
return rc;
}
--
2.20.1
^ permalink raw reply related [flat|nested] 4+ messages in thread