aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xattr.c')
-rw-r--r--fs/xattr.c85
1 files changed, 54 insertions, 31 deletions
diff --git a/fs/xattr.c b/fs/xattr.c
index 93dee70a1dbe..3f9c64bea151 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -16,6 +16,7 @@
16#include <linux/security.h> 16#include <linux/security.h>
17#include <linux/syscalls.h> 17#include <linux/syscalls.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/fsnotify.h>
19#include <asm/uaccess.h> 20#include <asm/uaccess.h>
20 21
21/* 22/*
@@ -50,18 +51,29 @@ setxattr(struct dentry *d, char __user *name, void __user *value,
50 } 51 }
51 } 52 }
52 53
54 down(&d->d_inode->i_sem);
55 error = security_inode_setxattr(d, kname, kvalue, size, flags);
56 if (error)
57 goto out;
53 error = -EOPNOTSUPP; 58 error = -EOPNOTSUPP;
54 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) { 59 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
55 down(&d->d_inode->i_sem); 60 error = d->d_inode->i_op->setxattr(d, kname, kvalue,
56 error = security_inode_setxattr(d, kname, kvalue, size, flags); 61 size, flags);
57 if (error) 62 if (!error) {
58 goto out; 63 fsnotify_xattr(d);
59 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags); 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);
60 if (!error) 72 if (!error)
61 security_inode_post_setxattr(d, kname, kvalue, size, flags); 73 fsnotify_xattr(d);
62out:
63 up(&d->d_inode->i_sem);
64 } 74 }
75out:
76 up(&d->d_inode->i_sem);
65 if (kvalue) 77 if (kvalue)
66 kfree(kvalue); 78 kfree(kvalue);
67 return error; 79 return error;
@@ -136,20 +148,25 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
136 return -ENOMEM; 148 return -ENOMEM;
137 } 149 }
138 150
151 error = security_inode_getxattr(d, kname);
152 if (error)
153 goto out;
139 error = -EOPNOTSUPP; 154 error = -EOPNOTSUPP;
140 if (d->d_inode->i_op && d->d_inode->i_op->getxattr) { 155 if (d->d_inode->i_op && d->d_inode->i_op->getxattr)
141 error = security_inode_getxattr(d, kname);
142 if (error)
143 goto out;
144 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); 156 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
145 if (error > 0) { 157 else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
146 if (size && copy_to_user(value, kvalue, error)) 158 sizeof XATTR_SECURITY_PREFIX - 1)) {
147 error = -EFAULT; 159 const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
148 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) { 160 error = security_inode_getsecurity(d->d_inode, suffix, kvalue,
149 /* The file system tried to returned a value bigger 161 size);
150 than XATTR_SIZE_MAX bytes. Not possible. */ 162 }
151 error = -E2BIG; 163 if (error > 0) {
152 } 164 if (size && copy_to_user(value, kvalue, error))
165 error = -EFAULT;
166 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
167 /* The file system tried to returned a value bigger
168 than XATTR_SIZE_MAX bytes. Not possible. */
169 error = -E2BIG;
153 } 170 }
154out: 171out:
155 if (kvalue) 172 if (kvalue)
@@ -218,20 +235,24 @@ listxattr(struct dentry *d, char __user *list, size_t size)
218 return -ENOMEM; 235 return -ENOMEM;
219 } 236 }
220 237
238 error = security_inode_listxattr(d);
239 if (error)
240 goto out;
221 error = -EOPNOTSUPP; 241 error = -EOPNOTSUPP;
222 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) { 242 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
223 error = security_inode_listxattr(d);
224 if (error)
225 goto out;
226 error = d->d_inode->i_op->listxattr(d, klist, size); 243 error = d->d_inode->i_op->listxattr(d, klist, size);
227 if (error > 0) { 244 } else {
228 if (size && copy_to_user(list, klist, error)) 245 error = security_inode_listsecurity(d->d_inode, klist, size);
229 error = -EFAULT; 246 if (size && error >= size)
230 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) { 247 error = -ERANGE;
231 /* The file system tried to returned a list bigger 248 }
232 than XATTR_LIST_MAX bytes. Not possible. */ 249 if (error > 0) {
233 error = -E2BIG; 250 if (size && copy_to_user(list, klist, error))
234 } 251 error = -EFAULT;
252 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
253 /* The file system tried to returned a list bigger
254 than XATTR_LIST_MAX bytes. Not possible. */
255 error = -E2BIG;
235 } 256 }
236out: 257out:
237 if (klist) 258 if (klist)
@@ -304,6 +325,8 @@ removexattr(struct dentry *d, char __user *name)
304 down(&d->d_inode->i_sem); 325 down(&d->d_inode->i_sem);
305 error = d->d_inode->i_op->removexattr(d, kname); 326 error = d->d_inode->i_op->removexattr(d, kname);
306 up(&d->d_inode->i_sem); 327 up(&d->d_inode->i_sem);
328 if (!error)
329 fsnotify_xattr(d);
307 } 330 }
308out: 331out:
309 return error; 332 return error;