aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xattr.c')
-rw-r--r--fs/xattr.c88
1 files changed, 56 insertions, 32 deletions
diff --git a/fs/xattr.c b/fs/xattr.c
index 6acd5c63da91..f6e00c0e114f 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -51,20 +51,29 @@ setxattr(struct dentry *d, char __user *name, void __user *value,
51 } 51 }
52 } 52 }
53 53
54 down(&d->d_inode->i_sem);
55 error = security_inode_setxattr(d, kname, kvalue, size, flags);
56 if (error)
57 goto out;
54 error = -EOPNOTSUPP; 58 error = -EOPNOTSUPP;
55 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) {
56 down(&d->d_inode->i_sem); 60 error = d->d_inode->i_op->setxattr(d, kname, kvalue,
57 error = security_inode_setxattr(d, kname, kvalue, size, flags); 61 size, flags);
58 if (error)
59 goto out;
60 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
61 if (!error) { 62 if (!error) {
62 fsnotify_xattr(d); 63 fsnotify_xattr(d);
63 security_inode_post_setxattr(d, kname, kvalue, size, flags); 64 security_inode_post_setxattr(d, kname, kvalue,
65 size, flags);
64 } 66 }
65out: 67 } else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
66 up(&d->d_inode->i_sem); 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);
67 } 74 }
75out:
76 up(&d->d_inode->i_sem);
68 if (kvalue) 77 if (kvalue)
69 kfree(kvalue); 78 kfree(kvalue);
70 return error; 79 return error;
@@ -134,25 +143,34 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
134 if (size) { 143 if (size) {
135 if (size > XATTR_SIZE_MAX) 144 if (size > XATTR_SIZE_MAX)
136 size = XATTR_SIZE_MAX; 145 size = XATTR_SIZE_MAX;
137 kvalue = kmalloc(size, GFP_KERNEL); 146 kvalue = kzalloc(size, GFP_KERNEL);
138 if (!kvalue) 147 if (!kvalue)
139 return -ENOMEM; 148 return -ENOMEM;
140 } 149 }
141 150
151 error = security_inode_getxattr(d, kname);
152 if (error)
153 goto out;
142 error = -EOPNOTSUPP; 154 error = -EOPNOTSUPP;
143 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)
144 error = security_inode_getxattr(d, kname);
145 if (error)
146 goto out;
147 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); 156 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
148 if (error > 0) { 157
149 if (size && copy_to_user(value, kvalue, error)) 158 if (!strncmp(kname, XATTR_SECURITY_PREFIX,
150 error = -EFAULT; 159 sizeof XATTR_SECURITY_PREFIX - 1)) {
151 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) { 160 const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
152 /* The file system tried to returned a value bigger 161 int rv = security_inode_getsecurity(d->d_inode, suffix, kvalue,
153 than XATTR_SIZE_MAX bytes. Not possible. */ 162 size, error);
154 error = -E2BIG; 163 /* Security module active: overwrite error value */
155 } 164 if (rv != -EOPNOTSUPP)
165 error = rv;
166 }
167 if (error > 0) {
168 if (size && copy_to_user(value, kvalue, error))
169 error = -EFAULT;
170 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
171 /* The file system tried to returned a value bigger
172 than XATTR_SIZE_MAX bytes. Not possible. */
173 error = -E2BIG;
156 } 174 }
157out: 175out:
158 if (kvalue) 176 if (kvalue)
@@ -221,20 +239,24 @@ listxattr(struct dentry *d, char __user *list, size_t size)
221 return -ENOMEM; 239 return -ENOMEM;
222 } 240 }
223 241
242 error = security_inode_listxattr(d);
243 if (error)
244 goto out;
224 error = -EOPNOTSUPP; 245 error = -EOPNOTSUPP;
225 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) { 246 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
226 error = security_inode_listxattr(d);
227 if (error)
228 goto out;
229 error = d->d_inode->i_op->listxattr(d, klist, size); 247 error = d->d_inode->i_op->listxattr(d, klist, size);
230 if (error > 0) { 248 } else {
231 if (size && copy_to_user(list, klist, error)) 249 error = security_inode_listsecurity(d->d_inode, klist, size);
232 error = -EFAULT; 250 if (size && error >= size)
233 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) { 251 error = -ERANGE;
234 /* The file system tried to returned a list bigger 252 }
235 than XATTR_LIST_MAX bytes. Not possible. */ 253 if (error > 0) {
236 error = -E2BIG; 254 if (size && copy_to_user(list, klist, error))
237 } 255 error = -EFAULT;
256 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
257 /* The file system tried to returned a list bigger
258 than XATTR_LIST_MAX bytes. Not possible. */
259 error = -E2BIG;
238 } 260 }
239out: 261out:
240 if (klist) 262 if (klist)
@@ -307,6 +329,8 @@ removexattr(struct dentry *d, char __user *name)
307 down(&d->d_inode->i_sem); 329 down(&d->d_inode->i_sem);
308 error = d->d_inode->i_op->removexattr(d, kname); 330 error = d->d_inode->i_op->removexattr(d, kname);
309 up(&d->d_inode->i_sem); 331 up(&d->d_inode->i_sem);
332 if (!error)
333 fsnotify_xattr(d);
310 } 334 }
311out: 335out:
312 return error; 336 return error;