Skip to content

Commit 5d6c319

Browse files
Andreas GruenbacherAl Viro
authored andcommitted
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 8 additions & 10 deletions
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

Lines changed: 6 additions & 7 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 33 additions & 11 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 10 additions & 15 deletions
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

Lines changed: 4 additions & 3 deletions
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
}

0 commit comments

Comments
 (0)