aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xattr.c
diff options
context:
space:
mode:
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