Skip to content

Commit 4b96024

Browse files
Paulo AlcantaraSteve French
authored andcommitted
smb: client: handle lack of FSCTL_GET_REPARSE_POINT support
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]>
1 parent 8400291 commit 4b96024

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
@@ -1042,13 +1042,26 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
10421042
}
10431043

10441044
rc = -EOPNOTSUPP;
1045-
switch ((data->reparse.tag = tag)) {
1046-
case 0: /* SMB1 symlink */
1045+
data->reparse.tag = tag;
1046+
if (!data->reparse.tag) {
10471047
if (server->ops->query_symlink) {
10481048
rc = server->ops->query_symlink(xid, tcon,
10491049
cifs_sb, full_path,
10501050
&data->symlink_target);
10511051
}
1052+
if (rc == -EOPNOTSUPP)
1053+
data->reparse.tag = IO_REPARSE_TAG_INTERNAL;
1054+
}
1055+
1056+
switch (data->reparse.tag) {
1057+
case 0: /* SMB1 symlink */
1058+
break;
1059+
case IO_REPARSE_TAG_INTERNAL:
1060+
rc = 0;
1061+
if (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY) {
1062+
cifs_create_junction_fattr(fattr, sb);
1063+
goto out;
1064+
}
10521065
break;
10531066
case IO_REPARSE_TAG_MOUNT_POINT:
10541067
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)