Skip to content

Commit 83e3bc2

Browse files
committed
retrieving CIFS ACLs when mounted with SMB2 fails dropping session
The get/set ACL xattr support for CIFS ACLs attempts to send old cifs dialect protocol requests even when mounted with SMB2 or later dialects. Sending cifs requests on an smb2 session causes problems - the server drops the session due to the illegal request. This patch makes CIFS ACL operations protocol specific to fix that. Attempting to query/set CIFS ACLs for SMB2 will now return EOPNOTSUPP (until we add worker routines for sending query ACL requests via SMB2) instead of sending invalid (cifs) requests. A separate followon patch will be needed to fix cifs_acl_to_fattr (which takes a cifs specific u16 fid so can't be abstracted to work with SMB2 until that is changed) and will be needed to fix mount problems when "cifsacl" is specified on mount with e.g. vers=2.1 Signed-off-by: Steve French <[email protected]> Reviewed-by: Shirish Pargaonkar <[email protected]> CC: Stable <[email protected]>
1 parent d979f3b commit 83e3bc2

File tree

4 files changed

+43
-8
lines changed

4 files changed

+43
-8
lines changed

fs/cifs/cifsacl.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,15 +1043,30 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
10431043
__u32 secdesclen = 0;
10441044
struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
10451045
struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1046+
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1047+
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1048+
struct cifs_tcon *tcon;
1049+
1050+
if (IS_ERR(tlink))
1051+
return PTR_ERR(tlink);
1052+
tcon = tlink_tcon(tlink);
10461053

10471054
cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
10481055

10491056
/* Get the security descriptor */
1050-
pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
1057+
1058+
if (tcon->ses->server->ops->get_acl == NULL) {
1059+
cifs_put_tlink(tlink);
1060+
return -EOPNOTSUPP;
1061+
}
1062+
1063+
pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
1064+
&secdesclen);
10511065
if (IS_ERR(pntsd)) {
10521066
rc = PTR_ERR(pntsd);
10531067
cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1054-
goto out;
1068+
cifs_put_tlink(tlink);
1069+
return rc;
10551070
}
10561071

10571072
/*
@@ -1064,6 +1079,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
10641079
pnntsd = kmalloc(secdesclen, GFP_KERNEL);
10651080
if (!pnntsd) {
10661081
kfree(pntsd);
1082+
cifs_put_tlink(tlink);
10671083
return -ENOMEM;
10681084
}
10691085

@@ -1072,14 +1088,18 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
10721088

10731089
cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
10741090

1091+
if (tcon->ses->server->ops->set_acl == NULL)
1092+
rc = -EOPNOTSUPP;
1093+
10751094
if (!rc) {
10761095
/* Set the security descriptor */
1077-
rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
1096+
rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode,
1097+
path, aclflag);
10781098
cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
10791099
}
1100+
cifs_put_tlink(tlink);
10801101

10811102
kfree(pnntsd);
10821103
kfree(pntsd);
1083-
out:
10841104
return rc;
10851105
}

fs/cifs/cifsglob.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,10 @@ struct smb_version_operations {
395395
int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
396396
const char *, const void *, const __u16,
397397
const struct nls_table *, int);
398+
struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
399+
const char *, u32 *);
400+
int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
401+
int);
398402
};
399403

400404
struct smb_version_values {

fs/cifs/smb1ops.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,10 @@ struct smb_version_operations smb1_operations = {
10711071
.query_all_EAs = CIFSSMBQAllEAs,
10721072
.set_EA = CIFSSMBSetEA,
10731073
#endif /* CIFS_XATTR */
1074+
#ifdef CONFIG_CIFS_ACL
1075+
.get_acl = get_cifs_acl,
1076+
.set_acl = set_cifs_acl,
1077+
#endif /* CIFS_ACL */
10741078
};
10751079

10761080
struct smb_version_values smb1_values = {

fs/cifs/xattr.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,12 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
176176
rc = -ENOMEM;
177177
} else {
178178
memcpy(pacl, ea_value, value_size);
179-
rc = set_cifs_acl(pacl, value_size,
180-
direntry->d_inode, full_path, CIFS_ACL_DACL);
179+
if (pTcon->ses->server->ops->set_acl)
180+
rc = pTcon->ses->server->ops->set_acl(pacl,
181+
value_size, direntry->d_inode,
182+
full_path, CIFS_ACL_DACL);
183+
else
184+
rc = -EOPNOTSUPP;
181185
if (rc == 0) /* force revalidate of the inode */
182186
CIFS_I(direntry->d_inode)->time = 0;
183187
kfree(pacl);
@@ -323,8 +327,11 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
323327
u32 acllen;
324328
struct cifs_ntsd *pacl;
325329

326-
pacl = get_cifs_acl(cifs_sb, direntry->d_inode,
327-
full_path, &acllen);
330+
if (pTcon->ses->server->ops->get_acl == NULL)
331+
goto get_ea_exit; /* rc already EOPNOTSUPP */
332+
333+
pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
334+
direntry->d_inode, full_path, &acllen);
328335
if (IS_ERR(pacl)) {
329336
rc = PTR_ERR(pacl);
330337
cifs_dbg(VFS, "%s: error %zd getting sec desc\n",

0 commit comments

Comments
 (0)