Commit 83e3bc23ef9ce7c03b7b4e5d3d790246ea59db3e

Authored by Steve French
1 parent d979f3b0a1

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

... ... @@ -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 }
... ... @@ -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 {
... ... @@ -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 = {
... ... @@ -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",