Skip to content

Commit 5d6c319

Browse files
Andreas GruenbacherAl Viro
Andreas Gruenbacher
authored and
Al Viro
committed
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 <[email protected]> Acked-by: James Morris <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent f5c2443 commit 5d6c319

File tree

14 files changed

+97
-85
lines changed

14 files changed

+97
-85
lines changed

fs/cachefiles/bind.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/mount.h>
2121
#include <linux/statfs.h>
2222
#include <linux/ctype.h>
23+
#include <linux/xattr.h>
2324
#include "internal.h"
2425

2526
static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches);
@@ -126,8 +127,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
126127
if (d_is_negative(root) ||
127128
!d_backing_inode(root)->i_op->lookup ||
128129
!d_backing_inode(root)->i_op->mkdir ||
129-
!d_backing_inode(root)->i_op->setxattr ||
130-
!d_backing_inode(root)->i_op->getxattr ||
130+
!(d_backing_inode(root)->i_opflags & IOP_XATTR) ||
131131
!root->d_sb->s_op->statfs ||
132132
!root->d_sb->s_op->sync_fs)
133133
goto error_unsupported;

fs/cachefiles/namei.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/namei.h>
2121
#include <linux/security.h>
2222
#include <linux/slab.h>
23+
#include <linux/xattr.h>
2324
#include "internal.h"
2425

2526
#define CACHEFILES_KEYBUF_SIZE 512
@@ -799,8 +800,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
799800
}
800801

801802
ret = -EPERM;
802-
if (!d_backing_inode(subdir)->i_op->setxattr ||
803-
!d_backing_inode(subdir)->i_op->getxattr ||
803+
if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) ||
804804
!d_backing_inode(subdir)->i_op->lookup ||
805805
!d_backing_inode(subdir)->i_op->mkdir ||
806806
!d_backing_inode(subdir)->i_op->create ||

fs/ecryptfs/inode.c

+8-10
Original file line numberDiff line numberDiff line change
@@ -1005,15 +1005,14 @@ ecryptfs_setxattr(struct dentry *dentry, struct inode *inode,
10051005
const char *name, const void *value,
10061006
size_t size, int flags)
10071007
{
1008-
int rc = 0;
1008+
int rc;
10091009
struct dentry *lower_dentry;
10101010

10111011
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)) {
10131013
rc = -EOPNOTSUPP;
10141014
goto out;
10151015
}
1016-
10171016
rc = vfs_setxattr(lower_dentry, name, value, size, flags);
10181017
if (!rc && inode)
10191018
fsstack_copy_attr_all(inode, d_inode(lower_dentry));
@@ -1025,15 +1024,14 @@ ssize_t
10251024
ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
10261025
const char *name, void *value, size_t size)
10271026
{
1028-
int rc = 0;
1027+
int rc;
10291028

1030-
if (!lower_inode->i_op->getxattr) {
1029+
if (!(lower_inode->i_opflags & IOP_XATTR)) {
10311030
rc = -EOPNOTSUPP;
10321031
goto out;
10331032
}
10341033
inode_lock(lower_inode);
1035-
rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
1036-
name, value, size);
1034+
rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
10371035
inode_unlock(lower_inode);
10381036
out:
10391037
return rc;
@@ -1069,18 +1067,18 @@ ecryptfs_listxattr(struct dentry *dentry, char *list, size_t size)
10691067
static int ecryptfs_removexattr(struct dentry *dentry, struct inode *inode,
10701068
const char *name)
10711069
{
1072-
int rc = 0;
1070+
int rc;
10731071
struct dentry *lower_dentry;
10741072
struct inode *lower_inode;
10751073

10761074
lower_dentry = ecryptfs_dentry_to_lower(dentry);
10771075
lower_inode = ecryptfs_inode_to_lower(inode);
1078-
if (!lower_inode->i_op->removexattr) {
1076+
if (!(lower_inode->i_opflags & IOP_XATTR)) {
10791077
rc = -EOPNOTSUPP;
10801078
goto out;
10811079
}
10821080
inode_lock(lower_inode);
1083-
rc = lower_inode->i_op->removexattr(lower_dentry, name);
1081+
rc = __vfs_removexattr(lower_dentry, name);
10841082
inode_unlock(lower_inode);
10851083
out:
10861084
return rc;

fs/ecryptfs/mmap.c

+6-7
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/file.h>
3333
#include <linux/scatterlist.h>
3434
#include <linux/slab.h>
35+
#include <linux/xattr.h>
3536
#include <asm/unaligned.h>
3637
#include "ecryptfs_kernel.h"
3738

@@ -422,7 +423,7 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
422423
struct inode *lower_inode = d_inode(lower_dentry);
423424
int rc;
424425

425-
if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
426+
if (!(lower_inode->i_opflags & IOP_XATTR)) {
426427
printk(KERN_WARNING
427428
"No support for setting xattr in lower filesystem\n");
428429
rc = -ENOSYS;
@@ -436,15 +437,13 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
436437
goto out;
437438
}
438439
inode_lock(lower_inode);
439-
size = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
440-
ECRYPTFS_XATTR_NAME,
441-
xattr_virt, PAGE_SIZE);
440+
size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
441+
xattr_virt, PAGE_SIZE);
442442
if (size < 0)
443443
size = 8;
444444
put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
445-
rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode,
446-
ECRYPTFS_XATTR_NAME,
447-
xattr_virt, size, 0);
445+
rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
446+
xattr_virt, size, 0);
448447
inode_unlock(lower_inode);
449448
if (rc)
450449
printk(KERN_ERR "Error whilst attempting to write inode size "

fs/overlayfs/copy_up.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
5858
char *buf, *name, *value = NULL;
5959
int uninitialized_var(error);
6060

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))
6363
return 0;
6464

6565
list_size = vfs_listxattr(old, NULL, 0);

fs/overlayfs/super.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,10 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
275275
char val;
276276
struct inode *inode = dentry->d_inode;
277277

278-
if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr)
278+
if (!S_ISDIR(inode->i_mode) || !(inode->i_opflags & IOP_XATTR))
279279
return false;
280280

281-
res = inode->i_op->getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
281+
res = __vfs_getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
282282
if (res == 1 && val == 'y')
283283
return true;
284284

fs/xattr.c

+33-11
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,16 @@ xattr_permission(struct inode *inode, const char *name, int mask)
136136
return inode_permission(inode, mask);
137137
}
138138

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+
139149
/**
140150
* __vfs_setxattr_noperm - perform setxattr operation without performing
141151
* permission checks.
@@ -163,7 +173,7 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
163173
if (issec)
164174
inode->i_flags &= ~S_NOSEC;
165175
if (inode->i_op->setxattr) {
166-
error = inode->i_op->setxattr(dentry, inode, name, value, size, flags);
176+
error = __vfs_setxattr(dentry, inode, name, value, size, flags);
167177
if (!error) {
168178
fsnotify_xattr(dentry);
169179
security_inode_post_setxattr(dentry, name, value,
@@ -274,6 +284,16 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
274284
return error;
275285
}
276286

287+
ssize_t
288+
__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
289+
void *value, size_t size)
290+
{
291+
if (!inode->i_op->getxattr)
292+
return -EOPNOTSUPP;
293+
return inode->i_op->getxattr(dentry, inode, name, value, size);
294+
}
295+
EXPORT_SYMBOL(__vfs_getxattr);
296+
277297
ssize_t
278298
vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
279299
{
@@ -301,13 +321,7 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
301321
return ret;
302322
}
303323
nolsm:
304-
if (inode->i_op->getxattr)
305-
error = inode->i_op->getxattr(dentry, inode, name, value, size);
306-
else
307-
error = -EOPNOTSUPP;
308-
309-
return error;
310-
324+
return __vfs_getxattr(dentry, inode, name, value, size);
311325
}
312326
EXPORT_SYMBOL_GPL(vfs_getxattr);
313327

@@ -332,13 +346,21 @@ vfs_listxattr(struct dentry *d, char *list, size_t size)
332346
EXPORT_SYMBOL_GPL(vfs_listxattr);
333347

334348
int
335-
vfs_removexattr(struct dentry *dentry, const char *name)
349+
__vfs_removexattr(struct dentry *dentry, const char *name)
336350
{
337351
struct inode *inode = dentry->d_inode;
338-
int error;
339352

340353
if (!inode->i_op->removexattr)
341354
return -EOPNOTSUPP;
355+
return inode->i_op->removexattr(dentry, name);
356+
}
357+
EXPORT_SYMBOL(__vfs_removexattr);
358+
359+
int
360+
vfs_removexattr(struct dentry *dentry, const char *name)
361+
{
362+
struct inode *inode = dentry->d_inode;
363+
int error;
342364

343365
error = xattr_permission(inode, name, MAY_WRITE);
344366
if (error)
@@ -349,7 +371,7 @@ vfs_removexattr(struct dentry *dentry, const char *name)
349371
if (error)
350372
goto out;
351373

352-
error = inode->i_op->removexattr(dentry, name);
374+
error = __vfs_removexattr(dentry, name);
353375

354376
if (!error) {
355377
fsnotify_xattr(dentry);

include/linux/xattr.h

+3
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,13 @@ struct xattr {
4646
};
4747

4848
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);
4950
ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
5051
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);
5153
int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, int);
5254
int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
55+
int __vfs_removexattr(struct dentry *, const char *);
5356
int vfs_removexattr(struct dentry *, const char *);
5457

5558
ssize_t generic_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size);

security/commoncap.c

+10-15
Original file line numberDiff line numberDiff line change
@@ -310,13 +310,8 @@ int cap_inode_need_killpriv(struct dentry *dentry)
310310
struct inode *inode = d_backing_inode(dentry);
311311
int error;
312312

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;
320315
}
321316

322317
/**
@@ -329,12 +324,12 @@ int cap_inode_need_killpriv(struct dentry *dentry)
329324
*/
330325
int cap_inode_killpriv(struct dentry *dentry)
331326
{
332-
struct inode *inode = d_backing_inode(dentry);
333-
334-
if (!inode->i_op->removexattr)
335-
return 0;
327+
int error;
336328

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;
338333
}
339334

340335
/*
@@ -394,11 +389,11 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
394389

395390
memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
396391

397-
if (!inode || !inode->i_op->getxattr)
392+
if (!inode)
398393
return -ENODATA;
399394

400-
size = inode->i_op->getxattr((struct dentry *)dentry, inode,
401-
XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ);
395+
size = __vfs_getxattr((struct dentry *)dentry, inode,
396+
XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ);
402397
if (size == -ENODATA || size == -EOPNOTSUPP)
403398
/* no data, that's ok */
404399
return -ENODATA;

security/integrity/evm/evm_crypto.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,9 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
182182
int error;
183183
int size;
184184

185-
if (!inode->i_op->getxattr)
185+
if (!(inode->i_opflags & IOP_XATTR))
186186
return -EOPNOTSUPP;
187+
187188
desc = init_desc(type);
188189
if (IS_ERR(desc))
189190
return PTR_ERR(desc);
@@ -253,8 +254,8 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
253254
rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
254255
&xattr_data,
255256
sizeof(xattr_data), 0);
256-
} else if (rc == -ENODATA && inode->i_op->removexattr) {
257-
rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM);
257+
} else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) {
258+
rc = __vfs_removexattr(dentry, XATTR_NAME_EVM);
258259
}
259260
return rc;
260261
}

security/integrity/evm/evm_main.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ static int evm_find_protected_xattrs(struct dentry *dentry)
7878
int error;
7979
int count = 0;
8080

81-
if (!inode->i_op->getxattr)
81+
if (!(inode->i_opflags & IOP_XATTR))
8282
return -EOPNOTSUPP;
8383

8484
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);
8686
if (error < 0) {
8787
if (error == -ENODATA)
8888
continue;

security/integrity/ima/ima_appraise.c

+10-11
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,13 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
165165
int ima_read_xattr(struct dentry *dentry,
166166
struct evm_ima_xattr_data **xattr_value)
167167
{
168-
struct inode *inode = d_backing_inode(dentry);
169-
170-
if (!inode->i_op->getxattr)
171-
return 0;
168+
ssize_t ret;
172169

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;
175175
}
176176

177177
/*
@@ -195,7 +195,7 @@ int ima_appraise_measurement(enum ima_hooks func,
195195
enum integrity_status status = INTEGRITY_UNKNOWN;
196196
int rc = xattr_len, hash_start = 0;
197197

198-
if (!inode->i_op->getxattr)
198+
if (!(inode->i_opflags & IOP_XATTR))
199199
return INTEGRITY_UNKNOWN;
200200

201201
if (rc <= 0) {
@@ -322,10 +322,10 @@ void ima_inode_post_setattr(struct dentry *dentry)
322322
{
323323
struct inode *inode = d_backing_inode(dentry);
324324
struct integrity_iint_cache *iint;
325-
int must_appraise, rc;
325+
int must_appraise;
326326

327327
if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
328-
|| !inode->i_op->removexattr)
328+
|| !(inode->i_opflags & IOP_XATTR))
329329
return;
330330

331331
must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
@@ -338,8 +338,7 @@ void ima_inode_post_setattr(struct dentry *dentry)
338338
iint->flags |= IMA_APPRAISE;
339339
}
340340
if (!must_appraise)
341-
rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA);
342-
return;
341+
__vfs_removexattr(dentry, XATTR_NAME_IMA);
343342
}
344343

345344
/*

0 commit comments

Comments
 (0)