aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xattr.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2006-01-09 23:51:55 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 11:01:29 -0500
commit5be196e5f925dab2309530fabce69c2e562b9791 (patch)
tree4249d808c38b6f13e899ac936585c1fbb48e5b3b /fs/xattr.c
parenta7e670d828e85ef9aacb7fa1cd221525c408110f (diff)
[PATCH] add vfs_* helpers for xattr operations
Add vfs_getxattr, vfs_setxattr and vfs_removexattr helpers for common checks around invocation of the xattr methods. NFSD already was missing some of the checks and there will be more soon. Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: James Morris <jmorris@namei.org> (James, I haven't touched selinux yet because it's doing various odd things and I'm not sure how it would interact with the security attribute fallbacks you added. Could you investigate whether it could use vfs_getxattr or if not add a __vfs_getxattr helper to share the bits it is fine with?) For NFSv4: instead of just converting it add an nfsd_getxattr helper for the code shared by NFSv2/3 and NFSv4 ACLs. In fact that code isn't even NFS-specific, but I'll wait for more users to pop up first before moving it to common code. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Dave Kleikamp <shaggy@austin.ibm.com> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Neil Brown <neilb@suse.de> Cc: Trond Myklebust <trond.myklebust@fys.uio.no> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/xattr.c')
-rw-r--r--fs/xattr.c146
1 files changed, 93 insertions, 53 deletions
diff --git a/fs/xattr.c b/fs/xattr.c
index 386a532ee5a9..fee804e69a9a 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -19,6 +19,96 @@
19#include <linux/fsnotify.h> 19#include <linux/fsnotify.h>
20#include <asm/uaccess.h> 20#include <asm/uaccess.h>
21 21
22
23int
24vfs_setxattr(struct dentry *dentry, char *name, void *value,
25 size_t size, int flags)
26{
27 struct inode *inode = dentry->d_inode;
28 int error;
29
30 mutex_lock(&inode->i_mutex);
31 error = security_inode_setxattr(dentry, name, value, size, flags);
32 if (error)
33 goto out;
34 error = -EOPNOTSUPP;
35 if (inode->i_op->setxattr) {
36 error = inode->i_op->setxattr(dentry, name, value, size, flags);
37 if (!error) {
38 fsnotify_xattr(dentry);
39 security_inode_post_setxattr(dentry, name, value,
40 size, flags);
41 }
42 } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
43 sizeof XATTR_SECURITY_PREFIX - 1)) {
44 const char *suffix = name + sizeof XATTR_SECURITY_PREFIX - 1;
45 error = security_inode_setsecurity(inode, suffix, value,
46 size, flags);
47 if (!error)
48 fsnotify_xattr(dentry);
49 }
50out:
51 mutex_unlock(&inode->i_mutex);
52 return error;
53}
54EXPORT_SYMBOL_GPL(vfs_setxattr);
55
56ssize_t
57vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
58{
59 struct inode *inode = dentry->d_inode;
60 int error;
61
62 error = security_inode_getxattr(dentry, name);
63 if (error)
64 return error;
65
66 if (inode->i_op->getxattr)
67 error = inode->i_op->getxattr(dentry, name, value, size);
68 else
69 error = -EOPNOTSUPP;
70
71 if (!strncmp(name, XATTR_SECURITY_PREFIX,
72 sizeof XATTR_SECURITY_PREFIX - 1)) {
73 const char *suffix = name + sizeof XATTR_SECURITY_PREFIX - 1;
74 int ret = security_inode_getsecurity(inode, suffix, value,
75 size, error);
76 /*
77 * Only overwrite the return value if a security module
78 * is actually active.
79 */
80 if (ret != -EOPNOTSUPP)
81 error = ret;
82 }
83
84 return error;
85}
86EXPORT_SYMBOL_GPL(vfs_getxattr);
87
88int
89vfs_removexattr(struct dentry *dentry, char *name)
90{
91 struct inode *inode = dentry->d_inode;
92 int error;
93
94 if (!inode->i_op->removexattr)
95 return -EOPNOTSUPP;
96
97 error = security_inode_removexattr(dentry, name);
98 if (error)
99 return error;
100
101 mutex_lock(&inode->i_mutex);
102 error = inode->i_op->removexattr(dentry, name);
103 mutex_unlock(&inode->i_mutex);
104
105 if (!error)
106 fsnotify_xattr(dentry);
107 return error;
108}
109EXPORT_SYMBOL_GPL(vfs_removexattr);
110
111
22/* 112/*
23 * Extended attribute SET operations 113 * Extended attribute SET operations
24 */ 114 */
@@ -51,29 +141,7 @@ setxattr(struct dentry *d, char __user *name, void __user *value,
51 } 141 }
52 } 142 }
53 143
54 mutex_lock(&d->d_inode->i_mutex); 144 error = vfs_setxattr(d, kname, kvalue, size, flags);
55 error = security_inode_setxattr(d, kname, kvalue, size, flags);
56 if (error)
57 goto out;
58 error = -EOPNOTSUPP;
59 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
60 error = d->d_inode->i_op->setxattr(d, kname, kvalue,
61 size, flags);
62 if (!error) {
63 fsnotify_xattr(d);
64 security_inode_post_setxattr(d, kname, kvalue,
65 size, flags);
66 }
67 } else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
68 sizeof XATTR_SECURITY_PREFIX - 1)) {
69 const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
70 error = security_inode_setsecurity(d->d_inode, suffix, kvalue,
71 size, flags);
72 if (!error)
73 fsnotify_xattr(d);
74 }
75out:
76 mutex_unlock(&d->d_inode->i_mutex);
77 kfree(kvalue); 145 kfree(kvalue);
78 return error; 146 return error;
79} 147}
@@ -147,22 +215,7 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
147 return -ENOMEM; 215 return -ENOMEM;
148 } 216 }
149 217
150 error = security_inode_getxattr(d, kname); 218 error = vfs_getxattr(d, kname, kvalue, size);
151 if (error)
152 goto out;
153 error = -EOPNOTSUPP;
154 if (d->d_inode->i_op && d->d_inode->i_op->getxattr)
155 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
156
157 if (!strncmp(kname, XATTR_SECURITY_PREFIX,
158 sizeof XATTR_SECURITY_PREFIX - 1)) {
159 const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
160 int rv = security_inode_getsecurity(d->d_inode, suffix, kvalue,
161 size, error);
162 /* Security module active: overwrite error value */
163 if (rv != -EOPNOTSUPP)
164 error = rv;
165 }
166 if (error > 0) { 219 if (error > 0) {
167 if (size && copy_to_user(value, kvalue, error)) 220 if (size && copy_to_user(value, kvalue, error))
168 error = -EFAULT; 221 error = -EFAULT;
@@ -171,7 +224,6 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
171 than XATTR_SIZE_MAX bytes. Not possible. */ 224 than XATTR_SIZE_MAX bytes. Not possible. */
172 error = -E2BIG; 225 error = -E2BIG;
173 } 226 }
174out:
175 kfree(kvalue); 227 kfree(kvalue);
176 return error; 228 return error;
177} 229}
@@ -318,19 +370,7 @@ removexattr(struct dentry *d, char __user *name)
318 if (error < 0) 370 if (error < 0)
319 return error; 371 return error;
320 372
321 error = -EOPNOTSUPP; 373 return vfs_removexattr(d, kname);
322 if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
323 error = security_inode_removexattr(d, kname);
324 if (error)
325 goto out;
326 mutex_lock(&d->d_inode->i_mutex);
327 error = d->d_inode->i_op->removexattr(d, kname);
328 mutex_unlock(&d->d_inode->i_mutex);
329 if (!error)
330 fsnotify_xattr(d);
331 }
332out:
333 return error;
334} 374}
335 375
336asmlinkage long 376asmlinkage long