]> bbs.cooldavid.org Git - net-next-2.6.git/blame - fs/xattr.c
[PATCH] tifm __iomem annotations, NULL noise removal
[net-next-2.6.git] / fs / xattr.c
CommitLineData
1da177e4
LT
1/*
2 File: fs/xattr.c
3
4 Extended attribute handling.
5
6 Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
7 Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
8 Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
9 */
10#include <linux/fs.h>
11#include <linux/slab.h>
12#include <linux/smp_lock.h>
13#include <linux/file.h>
14#include <linux/xattr.h>
15#include <linux/namei.h>
16#include <linux/security.h>
17#include <linux/syscalls.h>
18#include <linux/module.h>
0eeca283 19#include <linux/fsnotify.h>
73241ccc 20#include <linux/audit.h>
1da177e4
LT
21#include <asm/uaccess.h>
22
5be196e5 23
e0ad7b07
AM
24/*
25 * Check permissions for extended attribute access. This is a bit complicated
26 * because different namespaces have very different rules.
27 */
28static int
29xattr_permission(struct inode *inode, const char *name, int mask)
30{
31 /*
32 * We can never set or remove an extended attribute on a read-only
33 * filesystem or on an immutable / append-only inode.
34 */
35 if (mask & MAY_WRITE) {
36 if (IS_RDONLY(inode))
37 return -EROFS;
38 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
39 return -EPERM;
40 }
41
42 /*
43 * No restriction for security.* and system.* from the VFS. Decision
44 * on these is left to the underlying filesystem / security module.
45 */
46 if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
47 !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
48 return 0;
49
50 /*
51 * The trusted.* namespace can only accessed by a privilegued user.
52 */
53 if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
54 return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM);
55
56 if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
57 if (!S_ISREG(inode->i_mode) &&
58 (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
59 return -EPERM;
60 }
61
62 return permission(inode, mask, NULL);
63}
64
5be196e5
CH
65int
66vfs_setxattr(struct dentry *dentry, char *name, void *value,
67 size_t size, int flags)
68{
69 struct inode *inode = dentry->d_inode;
70 int error;
71
e0ad7b07
AM
72 error = xattr_permission(inode, name, MAY_WRITE);
73 if (error)
74 return error;
75
5be196e5
CH
76 mutex_lock(&inode->i_mutex);
77 error = security_inode_setxattr(dentry, name, value, size, flags);
78 if (error)
79 goto out;
80 error = -EOPNOTSUPP;
81 if (inode->i_op->setxattr) {
82 error = inode->i_op->setxattr(dentry, name, value, size, flags);
83 if (!error) {
84 fsnotify_xattr(dentry);
85 security_inode_post_setxattr(dentry, name, value,
86 size, flags);
87 }
88 } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
e0ad7b07
AM
89 XATTR_SECURITY_PREFIX_LEN)) {
90 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
5be196e5
CH
91 error = security_inode_setsecurity(inode, suffix, value,
92 size, flags);
93 if (!error)
94 fsnotify_xattr(dentry);
95 }
96out:
97 mutex_unlock(&inode->i_mutex);
98 return error;
99}
100EXPORT_SYMBOL_GPL(vfs_setxattr);
101
102ssize_t
103vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
104{
105 struct inode *inode = dentry->d_inode;
106 int error;
107
e0ad7b07
AM
108 error = xattr_permission(inode, name, MAY_READ);
109 if (error)
110 return error;
111
5be196e5
CH
112 error = security_inode_getxattr(dentry, name);
113 if (error)
114 return error;
115
116 if (inode->i_op->getxattr)
117 error = inode->i_op->getxattr(dentry, name, value, size);
118 else
119 error = -EOPNOTSUPP;
120
121 if (!strncmp(name, XATTR_SECURITY_PREFIX,
e0ad7b07
AM
122 XATTR_SECURITY_PREFIX_LEN)) {
123 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
5be196e5
CH
124 int ret = security_inode_getsecurity(inode, suffix, value,
125 size, error);
126 /*
127 * Only overwrite the return value if a security module
128 * is actually active.
129 */
130 if (ret != -EOPNOTSUPP)
131 error = ret;
132 }
133
134 return error;
135}
136EXPORT_SYMBOL_GPL(vfs_getxattr);
137
138int
139vfs_removexattr(struct dentry *dentry, char *name)
140{
141 struct inode *inode = dentry->d_inode;
142 int error;
143
144 if (!inode->i_op->removexattr)
145 return -EOPNOTSUPP;
146
e0ad7b07
AM
147 error = xattr_permission(inode, name, MAY_WRITE);
148 if (error)
149 return error;
150
5be196e5
CH
151 error = security_inode_removexattr(dentry, name);
152 if (error)
153 return error;
154
155 mutex_lock(&inode->i_mutex);
156 error = inode->i_op->removexattr(dentry, name);
157 mutex_unlock(&inode->i_mutex);
158
159 if (!error)
160 fsnotify_xattr(dentry);
161 return error;
162}
163EXPORT_SYMBOL_GPL(vfs_removexattr);
164
165
1da177e4
LT
166/*
167 * Extended attribute SET operations
168 */
169static long
170setxattr(struct dentry *d, char __user *name, void __user *value,
171 size_t size, int flags)
172{
173 int error;
174 void *kvalue = NULL;
175 char kname[XATTR_NAME_MAX + 1];
176
177 if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
178 return -EINVAL;
179
180 error = strncpy_from_user(kname, name, sizeof(kname));
181 if (error == 0 || error == sizeof(kname))
182 error = -ERANGE;
183 if (error < 0)
184 return error;
185
186 if (size) {
187 if (size > XATTR_SIZE_MAX)
188 return -E2BIG;
189 kvalue = kmalloc(size, GFP_KERNEL);
190 if (!kvalue)
191 return -ENOMEM;
192 if (copy_from_user(kvalue, value, size)) {
193 kfree(kvalue);
194 return -EFAULT;
195 }
196 }
197
5be196e5 198 error = vfs_setxattr(d, kname, kvalue, size, flags);
f99d49ad 199 kfree(kvalue);
1da177e4
LT
200 return error;
201}
202
203asmlinkage long
204sys_setxattr(char __user *path, char __user *name, void __user *value,
205 size_t size, int flags)
206{
207 struct nameidata nd;
208 int error;
209
210 error = user_path_walk(path, &nd);
211 if (error)
212 return error;
213 error = setxattr(nd.dentry, name, value, size, flags);
214 path_release(&nd);
215 return error;
216}
217
218asmlinkage long
219sys_lsetxattr(char __user *path, char __user *name, void __user *value,
220 size_t size, int flags)
221{
222 struct nameidata nd;
223 int error;
224
225 error = user_path_walk_link(path, &nd);
226 if (error)
227 return error;
228 error = setxattr(nd.dentry, name, value, size, flags);
229 path_release(&nd);
230 return error;
231}
232
233asmlinkage long
234sys_fsetxattr(int fd, char __user *name, void __user *value,
235 size_t size, int flags)
236{
237 struct file *f;
73241ccc 238 struct dentry *dentry;
1da177e4
LT
239 int error = -EBADF;
240
241 f = fget(fd);
242 if (!f)
243 return error;
73241ccc 244 dentry = f->f_dentry;
9c937dcc 245 audit_inode(NULL, dentry->d_inode);
73241ccc 246 error = setxattr(dentry, name, value, size, flags);
1da177e4
LT
247 fput(f);
248 return error;
249}
250
251/*
252 * Extended attribute GET operations
253 */
254static ssize_t
255getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
256{
257 ssize_t error;
258 void *kvalue = NULL;
259 char kname[XATTR_NAME_MAX + 1];
260
261 error = strncpy_from_user(kname, name, sizeof(kname));
262 if (error == 0 || error == sizeof(kname))
263 error = -ERANGE;
264 if (error < 0)
265 return error;
266
267 if (size) {
268 if (size > XATTR_SIZE_MAX)
269 size = XATTR_SIZE_MAX;
d381d8a9 270 kvalue = kzalloc(size, GFP_KERNEL);
1da177e4
LT
271 if (!kvalue)
272 return -ENOMEM;
273 }
274
5be196e5 275 error = vfs_getxattr(d, kname, kvalue, size);
f549d6c1
SS
276 if (error > 0) {
277 if (size && copy_to_user(value, kvalue, error))
278 error = -EFAULT;
279 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
280 /* The file system tried to returned a value bigger
281 than XATTR_SIZE_MAX bytes. Not possible. */
282 error = -E2BIG;
1da177e4 283 }
f99d49ad 284 kfree(kvalue);
1da177e4
LT
285 return error;
286}
287
288asmlinkage ssize_t
289sys_getxattr(char __user *path, char __user *name, void __user *value,
290 size_t size)
291{
292 struct nameidata nd;
293 ssize_t error;
294
295 error = user_path_walk(path, &nd);
296 if (error)
297 return error;
298 error = getxattr(nd.dentry, name, value, size);
299 path_release(&nd);
300 return error;
301}
302
303asmlinkage ssize_t
304sys_lgetxattr(char __user *path, char __user *name, void __user *value,
305 size_t size)
306{
307 struct nameidata nd;
308 ssize_t error;
309
310 error = user_path_walk_link(path, &nd);
311 if (error)
312 return error;
313 error = getxattr(nd.dentry, name, value, size);
314 path_release(&nd);
315 return error;
316}
317
318asmlinkage ssize_t
319sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
320{
321 struct file *f;
322 ssize_t error = -EBADF;
323
324 f = fget(fd);
325 if (!f)
326 return error;
327 error = getxattr(f->f_dentry, name, value, size);
328 fput(f);
329 return error;
330}
331
332/*
333 * Extended attribute LIST operations
334 */
335static ssize_t
336listxattr(struct dentry *d, char __user *list, size_t size)
337{
338 ssize_t error;
339 char *klist = NULL;
340
341 if (size) {
342 if (size > XATTR_LIST_MAX)
343 size = XATTR_LIST_MAX;
344 klist = kmalloc(size, GFP_KERNEL);
345 if (!klist)
346 return -ENOMEM;
347 }
348
f549d6c1
SS
349 error = security_inode_listxattr(d);
350 if (error)
351 goto out;
1da177e4
LT
352 error = -EOPNOTSUPP;
353 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
1da177e4 354 error = d->d_inode->i_op->listxattr(d, klist, size);
f549d6c1
SS
355 } else {
356 error = security_inode_listsecurity(d->d_inode, klist, size);
894ec870 357 if (size && error > size)
f549d6c1
SS
358 error = -ERANGE;
359 }
360 if (error > 0) {
361 if (size && copy_to_user(list, klist, error))
362 error = -EFAULT;
363 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
364 /* The file system tried to returned a list bigger
365 than XATTR_LIST_MAX bytes. Not possible. */
366 error = -E2BIG;
1da177e4
LT
367 }
368out:
f99d49ad 369 kfree(klist);
1da177e4
LT
370 return error;
371}
372
373asmlinkage ssize_t
374sys_listxattr(char __user *path, char __user *list, size_t size)
375{
376 struct nameidata nd;
377 ssize_t error;
378
379 error = user_path_walk(path, &nd);
380 if (error)
381 return error;
382 error = listxattr(nd.dentry, list, size);
383 path_release(&nd);
384 return error;
385}
386
387asmlinkage ssize_t
388sys_llistxattr(char __user *path, char __user *list, size_t size)
389{
390 struct nameidata nd;
391 ssize_t error;
392
393 error = user_path_walk_link(path, &nd);
394 if (error)
395 return error;
396 error = listxattr(nd.dentry, list, size);
397 path_release(&nd);
398 return error;
399}
400
401asmlinkage ssize_t
402sys_flistxattr(int fd, char __user *list, size_t size)
403{
404 struct file *f;
405 ssize_t error = -EBADF;
406
407 f = fget(fd);
408 if (!f)
409 return error;
410 error = listxattr(f->f_dentry, list, size);
411 fput(f);
412 return error;
413}
414
415/*
416 * Extended attribute REMOVE operations
417 */
418static long
419removexattr(struct dentry *d, char __user *name)
420{
421 int error;
422 char kname[XATTR_NAME_MAX + 1];
423
424 error = strncpy_from_user(kname, name, sizeof(kname));
425 if (error == 0 || error == sizeof(kname))
426 error = -ERANGE;
427 if (error < 0)
428 return error;
429
5be196e5 430 return vfs_removexattr(d, kname);
1da177e4
LT
431}
432
433asmlinkage long
434sys_removexattr(char __user *path, char __user *name)
435{
436 struct nameidata nd;
437 int error;
438
439 error = user_path_walk(path, &nd);
440 if (error)
441 return error;
442 error = removexattr(nd.dentry, name);
443 path_release(&nd);
444 return error;
445}
446
447asmlinkage long
448sys_lremovexattr(char __user *path, char __user *name)
449{
450 struct nameidata nd;
451 int error;
452
453 error = user_path_walk_link(path, &nd);
454 if (error)
455 return error;
456 error = removexattr(nd.dentry, name);
457 path_release(&nd);
458 return error;
459}
460
461asmlinkage long
462sys_fremovexattr(int fd, char __user *name)
463{
464 struct file *f;
73241ccc 465 struct dentry *dentry;
1da177e4
LT
466 int error = -EBADF;
467
468 f = fget(fd);
469 if (!f)
470 return error;
73241ccc 471 dentry = f->f_dentry;
9c937dcc 472 audit_inode(NULL, dentry->d_inode);
73241ccc 473 error = removexattr(dentry, name);
1da177e4
LT
474 fput(f);
475 return error;
476}
477
478
479static const char *
480strcmp_prefix(const char *a, const char *a_prefix)
481{
482 while (*a_prefix && *a == *a_prefix) {
483 a++;
484 a_prefix++;
485 }
486 return *a_prefix ? NULL : a;
487}
488
489/*
490 * In order to implement different sets of xattr operations for each xattr
491 * prefix with the generic xattr API, a filesystem should create a
492 * null-terminated array of struct xattr_handler (one for each prefix) and
493 * hang a pointer to it off of the s_xattr field of the superblock.
494 *
495 * The generic_fooxattr() functions will use this list to dispatch xattr
496 * operations to the correct xattr_handler.
497 */
498#define for_each_xattr_handler(handlers, handler) \
499 for ((handler) = *(handlers)++; \
500 (handler) != NULL; \
501 (handler) = *(handlers)++)
502
503/*
504 * Find the xattr_handler with the matching prefix.
505 */
506static struct xattr_handler *
507xattr_resolve_name(struct xattr_handler **handlers, const char **name)
508{
509 struct xattr_handler *handler;
510
511 if (!*name)
512 return NULL;
513
514 for_each_xattr_handler(handlers, handler) {
515 const char *n = strcmp_prefix(*name, handler->prefix);
516 if (n) {
517 *name = n;
518 break;
519 }
520 }
521 return handler;
522}
523
524/*
525 * Find the handler for the prefix and dispatch its get() operation.
526 */
527ssize_t
528generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
529{
530 struct xattr_handler *handler;
531 struct inode *inode = dentry->d_inode;
532
533 handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
534 if (!handler)
535 return -EOPNOTSUPP;
536 return handler->get(inode, name, buffer, size);
537}
538
539/*
540 * Combine the results of the list() operation from every xattr_handler in the
541 * list.
542 */
543ssize_t
544generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
545{
546 struct inode *inode = dentry->d_inode;
547 struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr;
548 unsigned int size = 0;
549
550 if (!buffer) {
551 for_each_xattr_handler(handlers, handler)
552 size += handler->list(inode, NULL, 0, NULL, 0);
553 } else {
554 char *buf = buffer;
555
556 for_each_xattr_handler(handlers, handler) {
557 size = handler->list(inode, buf, buffer_size, NULL, 0);
558 if (size > buffer_size)
559 return -ERANGE;
560 buf += size;
561 buffer_size -= size;
562 }
563 size = buf - buffer;
564 }
565 return size;
566}
567
568/*
569 * Find the handler for the prefix and dispatch its set() operation.
570 */
571int
572generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
573{
574 struct xattr_handler *handler;
575 struct inode *inode = dentry->d_inode;
576
577 if (size == 0)
578 value = ""; /* empty EA, do not remove */
579 handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
580 if (!handler)
581 return -EOPNOTSUPP;
582 return handler->set(inode, name, value, size, flags);
583}
584
585/*
586 * Find the handler for the prefix and dispatch its set() operation to remove
587 * any associated extended attribute.
588 */
589int
590generic_removexattr(struct dentry *dentry, const char *name)
591{
592 struct xattr_handler *handler;
593 struct inode *inode = dentry->d_inode;
594
595 handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
596 if (!handler)
597 return -EOPNOTSUPP;
598 return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
599}
600
601EXPORT_SYMBOL(generic_getxattr);
602EXPORT_SYMBOL(generic_listxattr);
603EXPORT_SYMBOL(generic_setxattr);
604EXPORT_SYMBOL(generic_removexattr);