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