[PATCH] add vfs_* helpers for xattr operations
[linux-2.6.git] / fs / xattr.c
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>
19 #include <linux/fsnotify.h>
20 #include <asm/uaccess.h>
21
22
23 int
24 vfs_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         }
50 out:
51         mutex_unlock(&inode->i_mutex);
52         return error;
53 }
54 EXPORT_SYMBOL_GPL(vfs_setxattr);
55
56 ssize_t
57 vfs_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 }
86 EXPORT_SYMBOL_GPL(vfs_getxattr);
87
88 int
89 vfs_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 }
109 EXPORT_SYMBOL_GPL(vfs_removexattr);
110
111
112 /*
113  * Extended attribute SET operations
114  */
115 static long
116 setxattr(struct dentry *d, char __user *name, void __user *value,
117          size_t size, int flags)
118 {
119         int error;
120         void *kvalue = NULL;
121         char kname[XATTR_NAME_MAX + 1];
122
123         if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
124                 return -EINVAL;
125
126         error = strncpy_from_user(kname, name, sizeof(kname));
127         if (error == 0 || error == sizeof(kname))
128                 error = -ERANGE;
129         if (error < 0)
130                 return error;
131
132         if (size) {
133                 if (size > XATTR_SIZE_MAX)
134                         return -E2BIG;
135                 kvalue = kmalloc(size, GFP_KERNEL);
136                 if (!kvalue)
137                         return -ENOMEM;
138                 if (copy_from_user(kvalue, value, size)) {
139                         kfree(kvalue);
140                         return -EFAULT;
141                 }
142         }
143
144         error = vfs_setxattr(d, kname, kvalue, size, flags);
145         kfree(kvalue);
146         return error;
147 }
148
149 asmlinkage long
150 sys_setxattr(char __user *path, char __user *name, void __user *value,
151              size_t size, int flags)
152 {
153         struct nameidata nd;
154         int error;
155
156         error = user_path_walk(path, &nd);
157         if (error)
158                 return error;
159         error = setxattr(nd.dentry, name, value, size, flags);
160         path_release(&nd);
161         return error;
162 }
163
164 asmlinkage long
165 sys_lsetxattr(char __user *path, char __user *name, void __user *value,
166               size_t size, int flags)
167 {
168         struct nameidata nd;
169         int error;
170
171         error = user_path_walk_link(path, &nd);
172         if (error)
173                 return error;
174         error = setxattr(nd.dentry, name, value, size, flags);
175         path_release(&nd);
176         return error;
177 }
178
179 asmlinkage long
180 sys_fsetxattr(int fd, char __user *name, void __user *value,
181               size_t size, int flags)
182 {
183         struct file *f;
184         int error = -EBADF;
185
186         f = fget(fd);
187         if (!f)
188                 return error;
189         error = setxattr(f->f_dentry, name, value, size, flags);
190         fput(f);
191         return error;
192 }
193
194 /*
195  * Extended attribute GET operations
196  */
197 static ssize_t
198 getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
199 {
200         ssize_t error;
201         void *kvalue = NULL;
202         char kname[XATTR_NAME_MAX + 1];
203
204         error = strncpy_from_user(kname, name, sizeof(kname));
205         if (error == 0 || error == sizeof(kname))
206                 error = -ERANGE;
207         if (error < 0)
208                 return error;
209
210         if (size) {
211                 if (size > XATTR_SIZE_MAX)
212                         size = XATTR_SIZE_MAX;
213                 kvalue = kzalloc(size, GFP_KERNEL);
214                 if (!kvalue)
215                         return -ENOMEM;
216         }
217
218         error = vfs_getxattr(d, kname, kvalue, size);
219         if (error > 0) {
220                 if (size && copy_to_user(value, kvalue, error))
221                         error = -EFAULT;
222         } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
223                 /* The file system tried to returned a value bigger
224                    than XATTR_SIZE_MAX bytes. Not possible. */
225                 error = -E2BIG;
226         }
227         kfree(kvalue);
228         return error;
229 }
230
231 asmlinkage ssize_t
232 sys_getxattr(char __user *path, char __user *name, void __user *value,
233              size_t size)
234 {
235         struct nameidata nd;
236         ssize_t error;
237
238         error = user_path_walk(path, &nd);
239         if (error)
240                 return error;
241         error = getxattr(nd.dentry, name, value, size);
242         path_release(&nd);
243         return error;
244 }
245
246 asmlinkage ssize_t
247 sys_lgetxattr(char __user *path, char __user *name, void __user *value,
248               size_t size)
249 {
250         struct nameidata nd;
251         ssize_t error;
252
253         error = user_path_walk_link(path, &nd);
254         if (error)
255                 return error;
256         error = getxattr(nd.dentry, name, value, size);
257         path_release(&nd);
258         return error;
259 }
260
261 asmlinkage ssize_t
262 sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
263 {
264         struct file *f;
265         ssize_t error = -EBADF;
266
267         f = fget(fd);
268         if (!f)
269                 return error;
270         error = getxattr(f->f_dentry, name, value, size);
271         fput(f);
272         return error;
273 }
274
275 /*
276  * Extended attribute LIST operations
277  */
278 static ssize_t
279 listxattr(struct dentry *d, char __user *list, size_t size)
280 {
281         ssize_t error;
282         char *klist = NULL;
283
284         if (size) {
285                 if (size > XATTR_LIST_MAX)
286                         size = XATTR_LIST_MAX;
287                 klist = kmalloc(size, GFP_KERNEL);
288                 if (!klist)
289                         return -ENOMEM;
290         }
291
292         error = security_inode_listxattr(d);
293         if (error)
294                 goto out;
295         error = -EOPNOTSUPP;
296         if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
297                 error = d->d_inode->i_op->listxattr(d, klist, size);
298         } else {
299                 error = security_inode_listsecurity(d->d_inode, klist, size);
300                 if (size && error > size)
301                         error = -ERANGE;
302         }
303         if (error > 0) {
304                 if (size && copy_to_user(list, klist, error))
305                         error = -EFAULT;
306         } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
307                 /* The file system tried to returned a list bigger
308                    than XATTR_LIST_MAX bytes. Not possible. */
309                 error = -E2BIG;
310         }
311 out:
312         kfree(klist);
313         return error;
314 }
315
316 asmlinkage ssize_t
317 sys_listxattr(char __user *path, char __user *list, size_t size)
318 {
319         struct nameidata nd;
320         ssize_t error;
321
322         error = user_path_walk(path, &nd);
323         if (error)
324                 return error;
325         error = listxattr(nd.dentry, list, size);
326         path_release(&nd);
327         return error;
328 }
329
330 asmlinkage ssize_t
331 sys_llistxattr(char __user *path, char __user *list, size_t size)
332 {
333         struct nameidata nd;
334         ssize_t error;
335
336         error = user_path_walk_link(path, &nd);
337         if (error)
338                 return error;
339         error = listxattr(nd.dentry, list, size);
340         path_release(&nd);
341         return error;
342 }
343
344 asmlinkage ssize_t
345 sys_flistxattr(int fd, char __user *list, size_t size)
346 {
347         struct file *f;
348         ssize_t error = -EBADF;
349
350         f = fget(fd);
351         if (!f)
352                 return error;
353         error = listxattr(f->f_dentry, list, size);
354         fput(f);
355         return error;
356 }
357
358 /*
359  * Extended attribute REMOVE operations
360  */
361 static long
362 removexattr(struct dentry *d, char __user *name)
363 {
364         int error;
365         char kname[XATTR_NAME_MAX + 1];
366
367         error = strncpy_from_user(kname, name, sizeof(kname));
368         if (error == 0 || error == sizeof(kname))
369                 error = -ERANGE;
370         if (error < 0)
371                 return error;
372
373         return vfs_removexattr(d, kname);
374 }
375
376 asmlinkage long
377 sys_removexattr(char __user *path, char __user *name)
378 {
379         struct nameidata nd;
380         int error;
381
382         error = user_path_walk(path, &nd);
383         if (error)
384                 return error;
385         error = removexattr(nd.dentry, name);
386         path_release(&nd);
387         return error;
388 }
389
390 asmlinkage long
391 sys_lremovexattr(char __user *path, char __user *name)
392 {
393         struct nameidata nd;
394         int error;
395
396         error = user_path_walk_link(path, &nd);
397         if (error)
398                 return error;
399         error = removexattr(nd.dentry, name);
400         path_release(&nd);
401         return error;
402 }
403
404 asmlinkage long
405 sys_fremovexattr(int fd, char __user *name)
406 {
407         struct file *f;
408         int error = -EBADF;
409
410         f = fget(fd);
411         if (!f)
412                 return error;
413         error = removexattr(f->f_dentry, name);
414         fput(f);
415         return error;
416 }
417
418
419 static const char *
420 strcmp_prefix(const char *a, const char *a_prefix)
421 {
422         while (*a_prefix && *a == *a_prefix) {
423                 a++;
424                 a_prefix++;
425         }
426         return *a_prefix ? NULL : a;
427 }
428
429 /*
430  * In order to implement different sets of xattr operations for each xattr
431  * prefix with the generic xattr API, a filesystem should create a
432  * null-terminated array of struct xattr_handler (one for each prefix) and
433  * hang a pointer to it off of the s_xattr field of the superblock.
434  *
435  * The generic_fooxattr() functions will use this list to dispatch xattr
436  * operations to the correct xattr_handler.
437  */
438 #define for_each_xattr_handler(handlers, handler)               \
439                 for ((handler) = *(handlers)++;                 \
440                         (handler) != NULL;                      \
441                         (handler) = *(handlers)++)
442
443 /*
444  * Find the xattr_handler with the matching prefix.
445  */
446 static struct xattr_handler *
447 xattr_resolve_name(struct xattr_handler **handlers, const char **name)
448 {
449         struct xattr_handler *handler;
450
451         if (!*name)
452                 return NULL;
453
454         for_each_xattr_handler(handlers, handler) {
455                 const char *n = strcmp_prefix(*name, handler->prefix);
456                 if (n) {
457                         *name = n;
458                         break;
459                 }
460         }
461         return handler;
462 }
463
464 /*
465  * Find the handler for the prefix and dispatch its get() operation.
466  */
467 ssize_t
468 generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
469 {
470         struct xattr_handler *handler;
471         struct inode *inode = dentry->d_inode;
472
473         handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
474         if (!handler)
475                 return -EOPNOTSUPP;
476         return handler->get(inode, name, buffer, size);
477 }
478
479 /*
480  * Combine the results of the list() operation from every xattr_handler in the
481  * list.
482  */
483 ssize_t
484 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
485 {
486         struct inode *inode = dentry->d_inode;
487         struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr;
488         unsigned int size = 0;
489
490         if (!buffer) {
491                 for_each_xattr_handler(handlers, handler)
492                         size += handler->list(inode, NULL, 0, NULL, 0);
493         } else {
494                 char *buf = buffer;
495
496                 for_each_xattr_handler(handlers, handler) {
497                         size = handler->list(inode, buf, buffer_size, NULL, 0);
498                         if (size > buffer_size)
499                                 return -ERANGE;
500                         buf += size;
501                         buffer_size -= size;
502                 }
503                 size = buf - buffer;
504         }
505         return size;
506 }
507
508 /*
509  * Find the handler for the prefix and dispatch its set() operation.
510  */
511 int
512 generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
513 {
514         struct xattr_handler *handler;
515         struct inode *inode = dentry->d_inode;
516
517         if (size == 0)
518                 value = "";  /* empty EA, do not remove */
519         handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
520         if (!handler)
521                 return -EOPNOTSUPP;
522         return handler->set(inode, name, value, size, flags);
523 }
524
525 /*
526  * Find the handler for the prefix and dispatch its set() operation to remove
527  * any associated extended attribute.
528  */
529 int
530 generic_removexattr(struct dentry *dentry, const char *name)
531 {
532         struct xattr_handler *handler;
533         struct inode *inode = dentry->d_inode;
534
535         handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
536         if (!handler)
537                 return -EOPNOTSUPP;
538         return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
539 }
540
541 EXPORT_SYMBOL(generic_getxattr);
542 EXPORT_SYMBOL(generic_listxattr);
543 EXPORT_SYMBOL(generic_setxattr);
544 EXPORT_SYMBOL(generic_removexattr);