Commit 83e3bc23ef9ce7c03b7b4e5d3d790246ea59db3e
1 parent
d979f3b0a1
Exists in
master
and in
16 other branches
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 <smfrench@gmail.com> Reviewed-by: Shirish Pargaonkar <spargaonkar@suse.com> CC: Stable <stable@kernel.org>
Showing 4 changed files with 43 additions and 8 deletions Side-by-side Diff
fs/cifs/cifsacl.c
... | ... | @@ -1043,15 +1043,30 @@ |
1043 | 1043 | __u32 secdesclen = 0; |
1044 | 1044 | struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ |
1045 | 1045 | 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; | |
1046 | 1049 | |
1050 | + if (IS_ERR(tlink)) | |
1051 | + return PTR_ERR(tlink); | |
1052 | + tcon = tlink_tcon(tlink); | |
1053 | + | |
1047 | 1054 | cifs_dbg(NOISY, "set ACL from mode for %s\n", path); |
1048 | 1055 | |
1049 | 1056 | /* 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); | |
1051 | 1065 | if (IS_ERR(pntsd)) { |
1052 | 1066 | rc = PTR_ERR(pntsd); |
1053 | 1067 | cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); |
1054 | - goto out; | |
1068 | + cifs_put_tlink(tlink); | |
1069 | + return rc; | |
1055 | 1070 | } |
1056 | 1071 | |
1057 | 1072 | /* |
... | ... | @@ -1064,6 +1079,7 @@ |
1064 | 1079 | pnntsd = kmalloc(secdesclen, GFP_KERNEL); |
1065 | 1080 | if (!pnntsd) { |
1066 | 1081 | kfree(pntsd); |
1082 | + cifs_put_tlink(tlink); | |
1067 | 1083 | return -ENOMEM; |
1068 | 1084 | } |
1069 | 1085 | |
1070 | 1086 | |
1071 | 1087 | |
1072 | 1088 | |
... | ... | @@ -1072,15 +1088,19 @@ |
1072 | 1088 | |
1073 | 1089 | cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); |
1074 | 1090 | |
1091 | + if (tcon->ses->server->ops->set_acl == NULL) | |
1092 | + rc = -EOPNOTSUPP; | |
1093 | + | |
1075 | 1094 | if (!rc) { |
1076 | 1095 | /* 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); | |
1078 | 1098 | cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc); |
1079 | 1099 | } |
1100 | + cifs_put_tlink(tlink); | |
1080 | 1101 | |
1081 | 1102 | kfree(pnntsd); |
1082 | 1103 | kfree(pntsd); |
1083 | -out: | |
1084 | 1104 | return rc; |
1085 | 1105 | } |
fs/cifs/cifsglob.h
... | ... | @@ -395,6 +395,10 @@ |
395 | 395 | int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, |
396 | 396 | const char *, const void *, const __u16, |
397 | 397 | 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); | |
398 | 402 | }; |
399 | 403 | |
400 | 404 | struct smb_version_values { |
fs/cifs/smb1ops.c
... | ... | @@ -1071,6 +1071,10 @@ |
1071 | 1071 | .query_all_EAs = CIFSSMBQAllEAs, |
1072 | 1072 | .set_EA = CIFSSMBSetEA, |
1073 | 1073 | #endif /* CIFS_XATTR */ |
1074 | +#ifdef CONFIG_CIFS_ACL | |
1075 | + .get_acl = get_cifs_acl, | |
1076 | + .set_acl = set_cifs_acl, | |
1077 | +#endif /* CIFS_ACL */ | |
1074 | 1078 | }; |
1075 | 1079 | |
1076 | 1080 | struct smb_version_values smb1_values = { |
fs/cifs/xattr.c
... | ... | @@ -176,8 +176,12 @@ |
176 | 176 | rc = -ENOMEM; |
177 | 177 | } else { |
178 | 178 | 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; | |
181 | 185 | if (rc == 0) /* force revalidate of the inode */ |
182 | 186 | CIFS_I(direntry->d_inode)->time = 0; |
183 | 187 | kfree(pacl); |
... | ... | @@ -323,8 +327,11 @@ |
323 | 327 | u32 acllen; |
324 | 328 | struct cifs_ntsd *pacl; |
325 | 329 | |
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); | |
328 | 335 | if (IS_ERR(pacl)) { |
329 | 336 | rc = PTR_ERR(pacl); |
330 | 337 | cifs_dbg(VFS, "%s: error %zd getting sec desc\n", |