aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2014-02-03 00:31:47 -0500
committerSteve French <smfrench@gmail.com>2014-02-07 12:08:17 -0500
commit83e3bc23ef9ce7c03b7b4e5d3d790246ea59db3e (patch)
tree956aac2ae24b12abc9be303bd74a890c480b434b /fs/cifs
parentd979f3b0a1f0b5499ab85e68cdf02b56852918b6 (diff)
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>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsacl.c28
-rw-r--r--fs/cifs/cifsglob.h4
-rw-r--r--fs/cifs/smb1ops.c4
-rw-r--r--fs/cifs/xattr.c15
4 files changed, 43 insertions, 8 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 8f9b4f710d4a..c819b0bd491a 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -1043,15 +1043,30 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1043 __u32 secdesclen = 0; 1043 __u32 secdesclen = 0;
1044 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ 1044 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1045 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ 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;
1049
1050 if (IS_ERR(tlink))
1051 return PTR_ERR(tlink);
1052 tcon = tlink_tcon(tlink);
1046 1053
1047 cifs_dbg(NOISY, "set ACL from mode for %s\n", path); 1054 cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
1048 1055
1049 /* Get the security descriptor */ 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 if (IS_ERR(pntsd)) { 1065 if (IS_ERR(pntsd)) {
1052 rc = PTR_ERR(pntsd); 1066 rc = PTR_ERR(pntsd);
1053 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); 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 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1064 pnntsd = kmalloc(secdesclen, GFP_KERNEL); 1079 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1065 if (!pnntsd) { 1080 if (!pnntsd) {
1066 kfree(pntsd); 1081 kfree(pntsd);
1082 cifs_put_tlink(tlink);
1067 return -ENOMEM; 1083 return -ENOMEM;
1068 } 1084 }
1069 1085
@@ -1072,14 +1088,18 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1072 1088
1073 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); 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 if (!rc) { 1094 if (!rc) {
1076 /* Set the security descriptor */ 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 cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc); 1098 cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
1079 } 1099 }
1100 cifs_put_tlink(tlink);
1080 1101
1081 kfree(pnntsd); 1102 kfree(pnntsd);
1082 kfree(pntsd); 1103 kfree(pntsd);
1083out:
1084 return rc; 1104 return rc;
1085} 1105}
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a245d1809ed8..615e35ab7ef6 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -395,6 +395,10 @@ struct smb_version_operations {
395 int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, 395 int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
396 const char *, const void *, const __u16, 396 const char *, const void *, const __u16,
397 const struct nls_table *, int); 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
400struct smb_version_values { 404struct smb_version_values {
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 3e4ff79e3031..bfd66d84831e 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -1071,6 +1071,10 @@ struct smb_version_operations smb1_operations = {
1071 .query_all_EAs = CIFSSMBQAllEAs, 1071 .query_all_EAs = CIFSSMBQAllEAs,
1072 .set_EA = CIFSSMBSetEA, 1072 .set_EA = CIFSSMBSetEA,
1073#endif /* CIFS_XATTR */ 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
1076struct smb_version_values smb1_values = { 1080struct smb_version_values smb1_values = {
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 95c43bb20335..5ac836a86b18 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -176,8 +176,12 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
176 rc = -ENOMEM; 176 rc = -ENOMEM;
177 } else { 177 } else {
178 memcpy(pacl, ea_value, value_size); 178 memcpy(pacl, ea_value, value_size);
179 rc = set_cifs_acl(pacl, value_size, 179 if (pTcon->ses->server->ops->set_acl)
180 direntry->d_inode, full_path, CIFS_ACL_DACL); 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 if (rc == 0) /* force revalidate of the inode */ 185 if (rc == 0) /* force revalidate of the inode */
182 CIFS_I(direntry->d_inode)->time = 0; 186 CIFS_I(direntry->d_inode)->time = 0;
183 kfree(pacl); 187 kfree(pacl);
@@ -323,8 +327,11 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
323 u32 acllen; 327 u32 acllen;
324 struct cifs_ntsd *pacl; 328 struct cifs_ntsd *pacl;
325 329
326 pacl = get_cifs_acl(cifs_sb, direntry->d_inode, 330 if (pTcon->ses->server->ops->get_acl == NULL)
327 full_path, &acllen); 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 if (IS_ERR(pacl)) { 335 if (IS_ERR(pacl)) {
329 rc = PTR_ERR(pacl); 336 rc = PTR_ERR(pacl);
330 cifs_dbg(VFS, "%s: error %zd getting sec desc\n", 337 cifs_dbg(VFS, "%s: error %zd getting sec desc\n",