aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2016-09-29 11:48:42 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2016-10-07 20:10:44 -0400
commit5d6c31910bc0713e37628dc0ce677dcb13c8ccf4 (patch)
treea28f96e71f09da2fbbde50882d56e5d5657c0ede /security
parentf5c244383725a6de06bc62fa7c54c0ea0d942eec (diff)
xattr: Add __vfs_{get,set,remove}xattr helpers
Right now, various places in the kernel check for the existence of getxattr, setxattr, and removexattr inode operations and directly call those operations. Switch to helper functions and test for the IOP_XATTR flag instead. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Acked-by: James Morris <james.l.morris@oracle.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'security')
-rw-r--r--security/commoncap.c25
-rw-r--r--security/integrity/evm/evm_crypto.c7
-rw-r--r--security/integrity/evm/evm_main.c4
-rw-r--r--security/integrity/ima/ima_appraise.c21
-rw-r--r--security/selinux/hooks.c19
-rw-r--r--security/smack/smack_lsm.c12
6 files changed, 39 insertions, 49 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index 14540bd78561..8df676fbd393 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -310,13 +310,8 @@ int cap_inode_need_killpriv(struct dentry *dentry)
310 struct inode *inode = d_backing_inode(dentry); 310 struct inode *inode = d_backing_inode(dentry);
311 int error; 311 int error;
312 312
313 if (!inode->i_op->getxattr) 313 error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
314 return 0; 314 return error > 0;
315
316 error = inode->i_op->getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
317 if (error <= 0)
318 return 0;
319 return 1;
320} 315}
321 316
322/** 317/**
@@ -329,12 +324,12 @@ int cap_inode_need_killpriv(struct dentry *dentry)
329 */ 324 */
330int cap_inode_killpriv(struct dentry *dentry) 325int cap_inode_killpriv(struct dentry *dentry)
331{ 326{
332 struct inode *inode = d_backing_inode(dentry); 327 int error;
333
334 if (!inode->i_op->removexattr)
335 return 0;
336 328
337 return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); 329 error = __vfs_removexattr(dentry, XATTR_NAME_CAPS);
330 if (error == -EOPNOTSUPP)
331 error = 0;
332 return error;
338} 333}
339 334
340/* 335/*
@@ -394,11 +389,11 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
394 389
395 memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); 390 memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
396 391
397 if (!inode || !inode->i_op->getxattr) 392 if (!inode)
398 return -ENODATA; 393 return -ENODATA;
399 394
400 size = inode->i_op->getxattr((struct dentry *)dentry, inode, 395 size = __vfs_getxattr((struct dentry *)dentry, inode,
401 XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ); 396 XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ);
402 if (size == -ENODATA || size == -EOPNOTSUPP) 397 if (size == -ENODATA || size == -EOPNOTSUPP)
403 /* no data, that's ok */ 398 /* no data, that's ok */
404 return -ENODATA; 399 return -ENODATA;
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index 11c1d30bd705..bf663915412e 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -182,8 +182,9 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
182 int error; 182 int error;
183 int size; 183 int size;
184 184
185 if (!inode->i_op->getxattr) 185 if (!(inode->i_opflags & IOP_XATTR))
186 return -EOPNOTSUPP; 186 return -EOPNOTSUPP;
187
187 desc = init_desc(type); 188 desc = init_desc(type);
188 if (IS_ERR(desc)) 189 if (IS_ERR(desc))
189 return PTR_ERR(desc); 190 return PTR_ERR(desc);
@@ -253,8 +254,8 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
253 rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, 254 rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
254 &xattr_data, 255 &xattr_data,
255 sizeof(xattr_data), 0); 256 sizeof(xattr_data), 0);
256 } else if (rc == -ENODATA && inode->i_op->removexattr) { 257 } else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) {
257 rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM); 258 rc = __vfs_removexattr(dentry, XATTR_NAME_EVM);
258 } 259 }
259 return rc; 260 return rc;
260} 261}
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index b9e26288d30c..ba8615576d4d 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -78,11 +78,11 @@ static int evm_find_protected_xattrs(struct dentry *dentry)
78 int error; 78 int error;
79 int count = 0; 79 int count = 0;
80 80
81 if (!inode->i_op->getxattr) 81 if (!(inode->i_opflags & IOP_XATTR))
82 return -EOPNOTSUPP; 82 return -EOPNOTSUPP;
83 83
84 for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) { 84 for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
85 error = inode->i_op->getxattr(dentry, inode, *xattr, NULL, 0); 85 error = __vfs_getxattr(dentry, inode, *xattr, NULL, 0);
86 if (error < 0) { 86 if (error < 0) {
87 if (error == -ENODATA) 87 if (error == -ENODATA)
88 continue; 88 continue;
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 4b9b4a4e1b89..0cc40af9c218 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -165,13 +165,13 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
165int ima_read_xattr(struct dentry *dentry, 165int ima_read_xattr(struct dentry *dentry,
166 struct evm_ima_xattr_data **xattr_value) 166 struct evm_ima_xattr_data **xattr_value)
167{ 167{
168 struct inode *inode = d_backing_inode(dentry); 168 ssize_t ret;
169
170 if (!inode->i_op->getxattr)
171 return 0;
172 169
173 return vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value, 170 ret = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
174 0, GFP_NOFS); 171 0, GFP_NOFS);
172 if (ret == -EOPNOTSUPP)
173 ret = 0;
174 return ret;
175} 175}
176 176
177/* 177/*
@@ -195,7 +195,7 @@ int ima_appraise_measurement(enum ima_hooks func,
195 enum integrity_status status = INTEGRITY_UNKNOWN; 195 enum integrity_status status = INTEGRITY_UNKNOWN;
196 int rc = xattr_len, hash_start = 0; 196 int rc = xattr_len, hash_start = 0;
197 197
198 if (!inode->i_op->getxattr) 198 if (!(inode->i_opflags & IOP_XATTR))
199 return INTEGRITY_UNKNOWN; 199 return INTEGRITY_UNKNOWN;
200 200
201 if (rc <= 0) { 201 if (rc <= 0) {
@@ -322,10 +322,10 @@ void ima_inode_post_setattr(struct dentry *dentry)
322{ 322{
323 struct inode *inode = d_backing_inode(dentry); 323 struct inode *inode = d_backing_inode(dentry);
324 struct integrity_iint_cache *iint; 324 struct integrity_iint_cache *iint;
325 int must_appraise, rc; 325 int must_appraise;
326 326
327 if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) 327 if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
328 || !inode->i_op->removexattr) 328 || !(inode->i_opflags & IOP_XATTR))
329 return; 329 return;
330 330
331 must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); 331 must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
@@ -338,8 +338,7 @@ void ima_inode_post_setattr(struct dentry *dentry)
338 iint->flags |= IMA_APPRAISE; 338 iint->flags |= IMA_APPRAISE;
339 } 339 }
340 if (!must_appraise) 340 if (!must_appraise)
341 rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA); 341 __vfs_removexattr(dentry, XATTR_NAME_IMA);
342 return;
343} 342}
344 343
345/* 344/*
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 13185a6c266a..3db31ac7986b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -507,14 +507,14 @@ static int sb_finish_set_opts(struct super_block *sb)
507 the root directory. -ENODATA is ok, as this may be 507 the root directory. -ENODATA is ok, as this may be
508 the first boot of the SELinux kernel before we have 508 the first boot of the SELinux kernel before we have
509 assigned xattr values to the filesystem. */ 509 assigned xattr values to the filesystem. */
510 if (!root_inode->i_op->getxattr) { 510 if (!(root_inode->i_opflags & IOP_XATTR)) {
511 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " 511 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
512 "xattr support\n", sb->s_id, sb->s_type->name); 512 "xattr support\n", sb->s_id, sb->s_type->name);
513 rc = -EOPNOTSUPP; 513 rc = -EOPNOTSUPP;
514 goto out; 514 goto out;
515 } 515 }
516 rc = root_inode->i_op->getxattr(root, root_inode, 516
517 XATTR_NAME_SELINUX, NULL, 0); 517 rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
518 if (rc < 0 && rc != -ENODATA) { 518 if (rc < 0 && rc != -ENODATA) {
519 if (rc == -EOPNOTSUPP) 519 if (rc == -EOPNOTSUPP)
520 printk(KERN_WARNING "SELinux: (dev %s, type " 520 printk(KERN_WARNING "SELinux: (dev %s, type "
@@ -1410,11 +1410,10 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1410 case SECURITY_FS_USE_NATIVE: 1410 case SECURITY_FS_USE_NATIVE:
1411 break; 1411 break;
1412 case SECURITY_FS_USE_XATTR: 1412 case SECURITY_FS_USE_XATTR:
1413 if (!inode->i_op->getxattr) { 1413 if (!(inode->i_opflags & IOP_XATTR)) {
1414 isec->sid = sbsec->def_sid; 1414 isec->sid = sbsec->def_sid;
1415 break; 1415 break;
1416 } 1416 }
1417
1418 /* Need a dentry, since the xattr API requires one. 1417 /* Need a dentry, since the xattr API requires one.
1419 Life would be simpler if we could just pass the inode. */ 1418 Life would be simpler if we could just pass the inode. */
1420 if (opt_dentry) { 1419 if (opt_dentry) {
@@ -1445,14 +1444,12 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1445 goto out_unlock; 1444 goto out_unlock;
1446 } 1445 }
1447 context[len] = '\0'; 1446 context[len] = '\0';
1448 rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX, 1447 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
1449 context, len);
1450 if (rc == -ERANGE) { 1448 if (rc == -ERANGE) {
1451 kfree(context); 1449 kfree(context);
1452 1450
1453 /* Need a larger buffer. Query for the right size. */ 1451 /* Need a larger buffer. Query for the right size. */
1454 rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX, 1452 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
1455 NULL, 0);
1456 if (rc < 0) { 1453 if (rc < 0) {
1457 dput(dentry); 1454 dput(dentry);
1458 goto out_unlock; 1455 goto out_unlock;
@@ -1465,9 +1462,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1465 goto out_unlock; 1462 goto out_unlock;
1466 } 1463 }
1467 context[len] = '\0'; 1464 context[len] = '\0';
1468 rc = inode->i_op->getxattr(dentry, inode, 1465 rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
1469 XATTR_NAME_SELINUX,
1470 context, len);
1471 } 1466 }
1472 dput(dentry); 1467 dput(dentry);
1473 if (rc < 0) { 1468 if (rc < 0) {
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 87a9741b0d02..516b3f50f23d 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -265,14 +265,14 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
265 char *buffer; 265 char *buffer;
266 struct smack_known *skp = NULL; 266 struct smack_known *skp = NULL;
267 267
268 if (ip->i_op->getxattr == NULL) 268 if (!(ip->i_opflags & IOP_XATTR))
269 return ERR_PTR(-EOPNOTSUPP); 269 return ERR_PTR(-EOPNOTSUPP);
270 270
271 buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL); 271 buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
272 if (buffer == NULL) 272 if (buffer == NULL)
273 return ERR_PTR(-ENOMEM); 273 return ERR_PTR(-ENOMEM);
274 274
275 rc = ip->i_op->getxattr(dp, ip, name, buffer, SMK_LONGLABEL); 275 rc = __vfs_getxattr(dp, ip, name, buffer, SMK_LONGLABEL);
276 if (rc < 0) 276 if (rc < 0)
277 skp = ERR_PTR(rc); 277 skp = ERR_PTR(rc);
278 else if (rc == 0) 278 else if (rc == 0)
@@ -3520,8 +3520,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
3520 * It would be curious if the label of the task 3520 * It would be curious if the label of the task
3521 * does not match that assigned. 3521 * does not match that assigned.
3522 */ 3522 */
3523 if (inode->i_op->getxattr == NULL) 3523 if (!(inode->i_opflags & IOP_XATTR))
3524 break; 3524 break;
3525 /* 3525 /*
3526 * Get the dentry for xattr. 3526 * Get the dentry for xattr.
3527 */ 3527 */
@@ -3545,12 +3545,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
3545 */ 3545 */
3546 if (isp->smk_flags & SMK_INODE_CHANGED) { 3546 if (isp->smk_flags & SMK_INODE_CHANGED) {
3547 isp->smk_flags &= ~SMK_INODE_CHANGED; 3547 isp->smk_flags &= ~SMK_INODE_CHANGED;
3548 rc = inode->i_op->setxattr(dp, inode, 3548 rc = __vfs_setxattr(dp, inode,
3549 XATTR_NAME_SMACKTRANSMUTE, 3549 XATTR_NAME_SMACKTRANSMUTE,
3550 TRANS_TRUE, TRANS_TRUE_SIZE, 3550 TRANS_TRUE, TRANS_TRUE_SIZE,
3551 0); 3551 0);
3552 } else { 3552 } else {
3553 rc = inode->i_op->getxattr(dp, inode, 3553 rc = __vfs_getxattr(dp, inode,
3554 XATTR_NAME_SMACKTRANSMUTE, trattr, 3554 XATTR_NAME_SMACKTRANSMUTE, trattr,
3555 TRANS_TRUE_SIZE); 3555 TRANS_TRUE_SIZE);
3556 if (rc >= 0 && strncmp(trattr, TRANS_TRUE, 3556 if (rc >= 0 && strncmp(trattr, TRANS_TRUE,