Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Andreas Gruenbacher and committed by
Al Viro
5d6c3191 f5c24438

+98 -86
+2 -2
fs/cachefiles/bind.c
··· 20 20 #include <linux/mount.h> 21 21 #include <linux/statfs.h> 22 22 #include <linux/ctype.h> 23 + #include <linux/xattr.h> 23 24 #include "internal.h" 24 25 25 26 static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches); ··· 127 126 if (d_is_negative(root) || 128 127 !d_backing_inode(root)->i_op->lookup || 129 128 !d_backing_inode(root)->i_op->mkdir || 130 - !d_backing_inode(root)->i_op->setxattr || 131 - !d_backing_inode(root)->i_op->getxattr || 129 + !(d_backing_inode(root)->i_opflags & IOP_XATTR) || 132 130 !root->d_sb->s_op->statfs || 133 131 !root->d_sb->s_op->sync_fs) 134 132 goto error_unsupported;
+2 -2
fs/cachefiles/namei.c
··· 20 20 #include <linux/namei.h> 21 21 #include <linux/security.h> 22 22 #include <linux/slab.h> 23 + #include <linux/xattr.h> 23 24 #include "internal.h" 24 25 25 26 #define CACHEFILES_KEYBUF_SIZE 512 ··· 800 799 } 801 800 802 801 ret = -EPERM; 803 - if (!d_backing_inode(subdir)->i_op->setxattr || 804 - !d_backing_inode(subdir)->i_op->getxattr || 802 + if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) || 805 803 !d_backing_inode(subdir)->i_op->lookup || 806 804 !d_backing_inode(subdir)->i_op->mkdir || 807 805 !d_backing_inode(subdir)->i_op->create ||
+8 -10
fs/ecryptfs/inode.c
··· 1005 1005 const char *name, const void *value, 1006 1006 size_t size, int flags) 1007 1007 { 1008 - int rc = 0; 1008 + int rc; 1009 1009 struct dentry *lower_dentry; 1010 1010 1011 1011 lower_dentry = ecryptfs_dentry_to_lower(dentry); 1012 - if (!d_inode(lower_dentry)->i_op->setxattr) { 1012 + if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) { 1013 1013 rc = -EOPNOTSUPP; 1014 1014 goto out; 1015 1015 } 1016 - 1017 1016 rc = vfs_setxattr(lower_dentry, name, value, size, flags); 1018 1017 if (!rc && inode) 1019 1018 fsstack_copy_attr_all(inode, d_inode(lower_dentry)); ··· 1024 1025 ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode, 1025 1026 const char *name, void *value, size_t size) 1026 1027 { 1027 - int rc = 0; 1028 + int rc; 1028 1029 1029 - if (!lower_inode->i_op->getxattr) { 1030 + if (!(lower_inode->i_opflags & IOP_XATTR)) { 1030 1031 rc = -EOPNOTSUPP; 1031 1032 goto out; 1032 1033 } 1033 1034 inode_lock(lower_inode); 1034 - rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode, 1035 - name, value, size); 1035 + rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size); 1036 1036 inode_unlock(lower_inode); 1037 1037 out: 1038 1038 return rc; ··· 1067 1069 static int ecryptfs_removexattr(struct dentry *dentry, struct inode *inode, 1068 1070 const char *name) 1069 1071 { 1070 - int rc = 0; 1072 + int rc; 1071 1073 struct dentry *lower_dentry; 1072 1074 struct inode *lower_inode; 1073 1075 1074 1076 lower_dentry = ecryptfs_dentry_to_lower(dentry); 1075 1077 lower_inode = ecryptfs_inode_to_lower(inode); 1076 - if (!lower_inode->i_op->removexattr) { 1078 + if (!(lower_inode->i_opflags & IOP_XATTR)) { 1077 1079 rc = -EOPNOTSUPP; 1078 1080 goto out; 1079 1081 } 1080 1082 inode_lock(lower_inode); 1081 - rc = lower_inode->i_op->removexattr(lower_dentry, name); 1083 + rc = __vfs_removexattr(lower_dentry, name); 1082 1084 inode_unlock(lower_inode); 1083 1085 out: 1084 1086 return rc;
+6 -7
fs/ecryptfs/mmap.c
··· 32 32 #include <linux/file.h> 33 33 #include <linux/scatterlist.h> 34 34 #include <linux/slab.h> 35 + #include <linux/xattr.h> 35 36 #include <asm/unaligned.h> 36 37 #include "ecryptfs_kernel.h" 37 38 ··· 423 422 struct inode *lower_inode = d_inode(lower_dentry); 424 423 int rc; 425 424 426 - if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) { 425 + if (!(lower_inode->i_opflags & IOP_XATTR)) { 427 426 printk(KERN_WARNING 428 427 "No support for setting xattr in lower filesystem\n"); 429 428 rc = -ENOSYS; ··· 437 436 goto out; 438 437 } 439 438 inode_lock(lower_inode); 440 - size = lower_inode->i_op->getxattr(lower_dentry, lower_inode, 441 - ECRYPTFS_XATTR_NAME, 442 - xattr_virt, PAGE_SIZE); 439 + size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME, 440 + xattr_virt, PAGE_SIZE); 443 441 if (size < 0) 444 442 size = 8; 445 443 put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt); 446 - rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode, 447 - ECRYPTFS_XATTR_NAME, 448 - xattr_virt, size, 0); 444 + rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME, 445 + xattr_virt, size, 0); 449 446 inode_unlock(lower_inode); 450 447 if (rc) 451 448 printk(KERN_ERR "Error whilst attempting to write inode size "
+2 -2
fs/overlayfs/copy_up.c
··· 58 58 char *buf, *name, *value = NULL; 59 59 int uninitialized_var(error); 60 60 61 - if (!old->d_inode->i_op->getxattr || 62 - !new->d_inode->i_op->getxattr) 61 + if (!(old->d_inode->i_opflags & IOP_XATTR) || 62 + !(new->d_inode->i_opflags & IOP_XATTR)) 63 63 return 0; 64 64 65 65 list_size = vfs_listxattr(old, NULL, 0);
+2 -2
fs/overlayfs/super.c
··· 275 275 char val; 276 276 struct inode *inode = dentry->d_inode; 277 277 278 - if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr) 278 + if (!S_ISDIR(inode->i_mode) || !(inode->i_opflags & IOP_XATTR)) 279 279 return false; 280 280 281 - res = inode->i_op->getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1); 281 + res = __vfs_getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1); 282 282 if (res == 1 && val == 'y') 283 283 return true; 284 284
+34 -12
fs/xattr.c
··· 136 136 return inode_permission(inode, mask); 137 137 } 138 138 139 + int 140 + __vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name, 141 + const void *value, size_t size, int flags) 142 + { 143 + if (!inode->i_op->setxattr) 144 + return -EOPNOTSUPP; 145 + return inode->i_op->setxattr(dentry, inode, name, value, size, flags); 146 + } 147 + EXPORT_SYMBOL(__vfs_setxattr); 148 + 139 149 /** 140 150 * __vfs_setxattr_noperm - perform setxattr operation without performing 141 151 * permission checks. ··· 173 163 if (issec) 174 164 inode->i_flags &= ~S_NOSEC; 175 165 if (inode->i_op->setxattr) { 176 - error = inode->i_op->setxattr(dentry, inode, name, value, size, flags); 166 + error = __vfs_setxattr(dentry, inode, name, value, size, flags); 177 167 if (!error) { 178 168 fsnotify_xattr(dentry); 179 169 security_inode_post_setxattr(dentry, name, value, ··· 285 275 } 286 276 287 277 ssize_t 278 + __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, 279 + void *value, size_t size) 280 + { 281 + if (!inode->i_op->getxattr) 282 + return -EOPNOTSUPP; 283 + return inode->i_op->getxattr(dentry, inode, name, value, size); 284 + } 285 + EXPORT_SYMBOL(__vfs_getxattr); 286 + 287 + ssize_t 288 288 vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) 289 289 { 290 290 struct inode *inode = dentry->d_inode; ··· 321 301 return ret; 322 302 } 323 303 nolsm: 324 - if (inode->i_op->getxattr) 325 - error = inode->i_op->getxattr(dentry, inode, name, value, size); 326 - else 327 - error = -EOPNOTSUPP; 328 - 329 - return error; 330 - 304 + return __vfs_getxattr(dentry, inode, name, value, size); 331 305 } 332 306 EXPORT_SYMBOL_GPL(vfs_getxattr); 333 307 ··· 346 332 EXPORT_SYMBOL_GPL(vfs_listxattr); 347 333 348 334 int 335 + __vfs_removexattr(struct dentry *dentry, const char *name) 336 + { 337 + struct inode *inode = dentry->d_inode; 338 + 339 + if (!inode->i_op->removexattr) 340 + return -EOPNOTSUPP; 341 + return inode->i_op->removexattr(dentry, name); 342 + } 343 + EXPORT_SYMBOL(__vfs_removexattr); 344 + 345 + int 349 346 vfs_removexattr(struct dentry *dentry, const char *name) 350 347 { 351 348 struct inode *inode = dentry->d_inode; 352 349 int error; 353 - 354 - if (!inode->i_op->removexattr) 355 - return -EOPNOTSUPP; 356 350 357 351 error = xattr_permission(inode, name, MAY_WRITE); 358 352 if (error) ··· 371 349 if (error) 372 350 goto out; 373 351 374 - error = inode->i_op->removexattr(dentry, name); 352 + error = __vfs_removexattr(dentry, name); 375 353 376 354 if (!error) { 377 355 fsnotify_xattr(dentry);
+3
include/linux/xattr.h
··· 46 46 }; 47 47 48 48 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t); 49 + ssize_t __vfs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t); 49 50 ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t); 50 51 ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); 52 + int __vfs_setxattr(struct dentry *, struct inode *, const char *, const void *, size_t, int); 51 53 int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, int); 52 54 int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int); 55 + int __vfs_removexattr(struct dentry *, const char *); 53 56 int vfs_removexattr(struct dentry *, const char *); 54 57 55 58 ssize_t generic_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size);
+10 -15
security/commoncap.c
··· 310 310 struct inode *inode = d_backing_inode(dentry); 311 311 int error; 312 312 313 - if (!inode->i_op->getxattr) 314 - return 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; 313 + error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0); 314 + return error > 0; 320 315 } 321 316 322 317 /** ··· 324 329 */ 325 330 int cap_inode_killpriv(struct dentry *dentry) 326 331 { 327 - struct inode *inode = d_backing_inode(dentry); 332 + int error; 328 333 329 - if (!inode->i_op->removexattr) 330 - return 0; 331 - 332 - return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); 334 + error = __vfs_removexattr(dentry, XATTR_NAME_CAPS); 335 + if (error == -EOPNOTSUPP) 336 + error = 0; 337 + return error; 333 338 } 334 339 335 340 /* ··· 389 394 390 395 memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); 391 396 392 - if (!inode || !inode->i_op->getxattr) 397 + if (!inode) 393 398 return -ENODATA; 394 399 395 - size = inode->i_op->getxattr((struct dentry *)dentry, inode, 396 - XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ); 400 + size = __vfs_getxattr((struct dentry *)dentry, inode, 401 + XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ); 397 402 if (size == -ENODATA || size == -EOPNOTSUPP) 398 403 /* no data, that's ok */ 399 404 return -ENODATA;
+4 -3
security/integrity/evm/evm_crypto.c
··· 182 182 int error; 183 183 int size; 184 184 185 - if (!inode->i_op->getxattr) 185 + if (!(inode->i_opflags & IOP_XATTR)) 186 186 return -EOPNOTSUPP; 187 + 187 188 desc = init_desc(type); 188 189 if (IS_ERR(desc)) 189 190 return PTR_ERR(desc); ··· 254 253 rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, 255 254 &xattr_data, 256 255 sizeof(xattr_data), 0); 257 - } else if (rc == -ENODATA && inode->i_op->removexattr) { 258 - rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM); 256 + } else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) { 257 + rc = __vfs_removexattr(dentry, XATTR_NAME_EVM); 259 258 } 260 259 return rc; 261 260 }
+2 -2
security/integrity/evm/evm_main.c
··· 78 78 int error; 79 79 int count = 0; 80 80 81 - if (!inode->i_op->getxattr) 81 + if (!(inode->i_opflags & IOP_XATTR)) 82 82 return -EOPNOTSUPP; 83 83 84 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 86 if (error < 0) { 87 87 if (error == -ENODATA) 88 88 continue;
+10 -11
security/integrity/ima/ima_appraise.c
··· 165 165 int ima_read_xattr(struct dentry *dentry, 166 166 struct evm_ima_xattr_data **xattr_value) 167 167 { 168 - struct inode *inode = d_backing_inode(dentry); 168 + ssize_t ret; 169 169 170 - if (!inode->i_op->getxattr) 171 - return 0; 172 - 173 - return vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value, 174 - 0, GFP_NOFS); 170 + ret = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value, 171 + 0, GFP_NOFS); 172 + if (ret == -EOPNOTSUPP) 173 + ret = 0; 174 + return ret; 175 175 } 176 176 177 177 /* ··· 195 195 enum integrity_status status = INTEGRITY_UNKNOWN; 196 196 int rc = xattr_len, hash_start = 0; 197 197 198 - if (!inode->i_op->getxattr) 198 + if (!(inode->i_opflags & IOP_XATTR)) 199 199 return INTEGRITY_UNKNOWN; 200 200 201 201 if (rc <= 0) { ··· 322 322 { 323 323 struct inode *inode = d_backing_inode(dentry); 324 324 struct integrity_iint_cache *iint; 325 - int must_appraise, rc; 325 + int must_appraise; 326 326 327 327 if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) 328 - || !inode->i_op->removexattr) 328 + || !(inode->i_opflags & IOP_XATTR)) 329 329 return; 330 330 331 331 must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); ··· 338 338 iint->flags |= IMA_APPRAISE; 339 339 } 340 340 if (!must_appraise) 341 - rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA); 342 - return; 341 + __vfs_removexattr(dentry, XATTR_NAME_IMA); 343 342 } 344 343 345 344 /*
+7 -12
security/selinux/hooks.c
··· 507 507 the root directory. -ENODATA is ok, as this may be 508 508 the first boot of the SELinux kernel before we have 509 509 assigned xattr values to the filesystem. */ 510 - if (!root_inode->i_op->getxattr) { 510 + if (!(root_inode->i_opflags & IOP_XATTR)) { 511 511 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " 512 512 "xattr support\n", sb->s_id, sb->s_type->name); 513 513 rc = -EOPNOTSUPP; 514 514 goto out; 515 515 } 516 - rc = root_inode->i_op->getxattr(root, root_inode, 517 - XATTR_NAME_SELINUX, NULL, 0); 516 + 517 + rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0); 518 518 if (rc < 0 && rc != -ENODATA) { 519 519 if (rc == -EOPNOTSUPP) 520 520 printk(KERN_WARNING "SELinux: (dev %s, type " ··· 1410 1410 case SECURITY_FS_USE_NATIVE: 1411 1411 break; 1412 1412 case SECURITY_FS_USE_XATTR: 1413 - if (!inode->i_op->getxattr) { 1413 + if (!(inode->i_opflags & IOP_XATTR)) { 1414 1414 isec->sid = sbsec->def_sid; 1415 1415 break; 1416 1416 } 1417 - 1418 1417 /* Need a dentry, since the xattr API requires one. 1419 1418 Life would be simpler if we could just pass the inode. */ 1420 1419 if (opt_dentry) { ··· 1444 1445 goto out_unlock; 1445 1446 } 1446 1447 context[len] = '\0'; 1447 - rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX, 1448 - context, len); 1448 + rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); 1449 1449 if (rc == -ERANGE) { 1450 1450 kfree(context); 1451 1451 1452 1452 /* Need a larger buffer. Query for the right size. */ 1453 - rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX, 1454 - NULL, 0); 1453 + rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0); 1455 1454 if (rc < 0) { 1456 1455 dput(dentry); 1457 1456 goto out_unlock; ··· 1462 1465 goto out_unlock; 1463 1466 } 1464 1467 context[len] = '\0'; 1465 - rc = inode->i_op->getxattr(dentry, inode, 1466 - XATTR_NAME_SELINUX, 1467 - context, len); 1468 + rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); 1468 1469 } 1469 1470 dput(dentry); 1470 1471 if (rc < 0) {
+6 -6
security/smack/smack_lsm.c
··· 265 265 char *buffer; 266 266 struct smack_known *skp = NULL; 267 267 268 - if (ip->i_op->getxattr == NULL) 268 + if (!(ip->i_opflags & IOP_XATTR)) 269 269 return ERR_PTR(-EOPNOTSUPP); 270 270 271 271 buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL); 272 272 if (buffer == NULL) 273 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 276 if (rc < 0) 277 277 skp = ERR_PTR(rc); 278 278 else if (rc == 0) ··· 3520 3520 * It would be curious if the label of the task 3521 3521 * does not match that assigned. 3522 3522 */ 3523 - if (inode->i_op->getxattr == NULL) 3524 - break; 3523 + if (!(inode->i_opflags & IOP_XATTR)) 3524 + break; 3525 3525 /* 3526 3526 * Get the dentry for xattr. 3527 3527 */ ··· 3545 3545 */ 3546 3546 if (isp->smk_flags & SMK_INODE_CHANGED) { 3547 3547 isp->smk_flags &= ~SMK_INODE_CHANGED; 3548 - rc = inode->i_op->setxattr(dp, inode, 3548 + rc = __vfs_setxattr(dp, inode, 3549 3549 XATTR_NAME_SMACKTRANSMUTE, 3550 3550 TRANS_TRUE, TRANS_TRUE_SIZE, 3551 3551 0); 3552 3552 } else { 3553 - rc = inode->i_op->getxattr(dp, inode, 3553 + rc = __vfs_getxattr(dp, inode, 3554 3554 XATTR_NAME_SMACKTRANSMUTE, trattr, 3555 3555 TRANS_TRUE_SIZE); 3556 3556 if (rc >= 0 && strncmp(trattr, TRANS_TRUE,