Skip to content

Commit 2b0984c

Browse files
committed
smb: client: handle lack of FSCTL_GET_REPARSE_POINT support
jira LE-2157 Rebuild_History Non-Buildable kernel-5.14.0-503.14.1.el9_5 commit-author Paulo Alcantara <[email protected]> commit 4b96024 As per MS-FSA 2.1.5.10.14, support for FSCTL_GET_REPARSE_POINT is optional and if the server doesn't support it, STATUS_INVALID_DEVICE_REQUEST must be returned for the operation. If we find files with reparse points and we can't read them due to lack of client or server support, just ignore it and then treat them as regular files or junctions. Fixes: 5f71ebc ("smb: client: parse reparse point flag in create response") Reported-by: Sebastian Steinbeisser <[email protected]> Tested-by: Sebastian Steinbeisser <[email protected]> Acked-by: Tom Talpey <[email protected]> Signed-off-by: Paulo Alcantara (Red Hat) <[email protected]> Signed-off-by: Steve French <[email protected]> (cherry picked from commit 4b96024) Signed-off-by: Jonathan Maple <[email protected]>
1 parent 98a4a07 commit 2b0984c

File tree

4 files changed

+38
-4
lines changed

4 files changed

+38
-4
lines changed

fs/smb/client/inode.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,13 +1021,26 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
10211021
}
10221022

10231023
rc = -EOPNOTSUPP;
1024-
switch ((data->reparse.tag = tag)) {
1025-
case 0: /* SMB1 symlink */
1024+
data->reparse.tag = tag;
1025+
if (!data->reparse.tag) {
10261026
if (server->ops->query_symlink) {
10271027
rc = server->ops->query_symlink(xid, tcon,
10281028
cifs_sb, full_path,
10291029
&data->symlink_target);
10301030
}
1031+
if (rc == -EOPNOTSUPP)
1032+
data->reparse.tag = IO_REPARSE_TAG_INTERNAL;
1033+
}
1034+
1035+
switch (data->reparse.tag) {
1036+
case 0: /* SMB1 symlink */
1037+
break;
1038+
case IO_REPARSE_TAG_INTERNAL:
1039+
rc = 0;
1040+
if (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY) {
1041+
cifs_create_junction_fattr(fattr, sb);
1042+
goto out;
1043+
}
10311044
break;
10321045
case IO_REPARSE_TAG_MOUNT_POINT:
10331046
cifs_create_junction_fattr(fattr, sb);

fs/smb/client/reparse.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,10 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
505505
}
506506

507507
switch (tag) {
508+
case IO_REPARSE_TAG_INTERNAL:
509+
if (!(fattr->cf_cifsattrs & ATTR_DIRECTORY))
510+
return false;
511+
fallthrough;
508512
case IO_REPARSE_TAG_DFS:
509513
case IO_REPARSE_TAG_DFSR:
510514
case IO_REPARSE_TAG_MOUNT_POINT:

fs/smb/client/reparse.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
#include "fs_context.h"
1313
#include "cifsglob.h"
1414

15+
/*
16+
* Used only by cifs.ko to ignore reparse points from files when client or
17+
* server doesn't support FSCTL_GET_REPARSE_POINT.
18+
*/
19+
#define IO_REPARSE_TAG_INTERNAL ((__u32)~0U)
20+
1521
static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf)
1622
{
1723
u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer);
@@ -78,10 +84,19 @@ static inline u32 reparse_mode_wsl_tag(mode_t mode)
7884
static inline bool reparse_inode_match(struct inode *inode,
7985
struct cifs_fattr *fattr)
8086
{
87+
struct cifsInodeInfo *cinode = CIFS_I(inode);
8188
struct timespec64 ctime = inode_get_ctime(inode);
8289

83-
return (CIFS_I(inode)->cifsAttrs & ATTR_REPARSE) &&
84-
CIFS_I(inode)->reparse_tag == fattr->cf_cifstag &&
90+
/*
91+
* Do not match reparse tags when client or server doesn't support
92+
* FSCTL_GET_REPARSE_POINT. @fattr->cf_cifstag should contain correct
93+
* reparse tag from query dir response but the client won't be able to
94+
* read the reparse point data anyway. This spares us a revalidation.
95+
*/
96+
if (cinode->reparse_tag != IO_REPARSE_TAG_INTERNAL &&
97+
cinode->reparse_tag != fattr->cf_cifstag)
98+
return false;
99+
return (cinode->cifsAttrs & ATTR_REPARSE) &&
85100
timespec64_equal(&ctime, &fattr->cf_ctime);
86101
}
87102

fs/smb/client/smb2inode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,8 @@ int smb2_query_path_info(const unsigned int xid,
930930

931931
switch (rc) {
932932
case 0:
933+
rc = parse_create_response(data, cifs_sb, &out_iov[0]);
934+
break;
933935
case -EOPNOTSUPP:
934936
/*
935937
* BB TODO: When support for special files added to Samba

0 commit comments

Comments
 (0)