[PATCH] nfsd4: slabify nfs4_files
[pandora-kernel.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 <asm/uaccess.h>
20
21 /*
22  * Extended attribute SET operations
23  */
24 static long
25 setxattr(struct dentry *d, char __user *name, void __user *value,
26          size_t size, int flags)
27 {
28         int error;
29         void *kvalue = NULL;
30         char kname[XATTR_NAME_MAX + 1];
31
32         if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
33                 return -EINVAL;
34
35         error = strncpy_from_user(kname, name, sizeof(kname));
36         if (error == 0 || error == sizeof(kname))
37                 error = -ERANGE;
38         if (error < 0)
39                 return error;
40
41         if (size) {
42                 if (size > XATTR_SIZE_MAX)
43                         return -E2BIG;
44                 kvalue = kmalloc(size, GFP_KERNEL);
45                 if (!kvalue)
46                         return -ENOMEM;
47                 if (copy_from_user(kvalue, value, size)) {
48                         kfree(kvalue);
49                         return -EFAULT;
50                 }
51         }
52
53         error = -EOPNOTSUPP;
54         if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
55                 down(&d->d_inode->i_sem);
56                 error = security_inode_setxattr(d, kname, kvalue, size, flags);
57                 if (error)
58                         goto out;
59                 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
60                 if (!error)
61                         security_inode_post_setxattr(d, kname, kvalue, size, flags);
62 out:
63                 up(&d->d_inode->i_sem);
64         }
65         if (kvalue)
66                 kfree(kvalue);
67         return error;
68 }
69
70 asmlinkage long
71 sys_setxattr(char __user *path, char __user *name, void __user *value,
72              size_t size, int flags)
73 {
74         struct nameidata nd;
75         int error;
76
77         error = user_path_walk(path, &nd);
78         if (error)
79                 return error;
80         error = setxattr(nd.dentry, name, value, size, flags);
81         path_release(&nd);
82         return error;
83 }
84
85 asmlinkage long
86 sys_lsetxattr(char __user *path, char __user *name, void __user *value,
87               size_t size, int flags)
88 {
89         struct nameidata nd;
90         int error;
91
92         error = user_path_walk_link(path, &nd);
93         if (error)
94                 return error;
95         error = setxattr(nd.dentry, name, value, size, flags);
96         path_release(&nd);
97         return error;
98 }
99
100 asmlinkage long
101 sys_fsetxattr(int fd, char __user *name, void __user *value,
102               size_t size, int flags)
103 {
104         struct file *f;
105         int error = -EBADF;
106
107         f = fget(fd);
108         if (!f)
109                 return error;
110         error = setxattr(f->f_dentry, name, value, size, flags);
111         fput(f);
112         return error;
113 }
114
115 /*
116  * Extended attribute GET operations
117  */
118 static ssize_t
119 getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
120 {
121         ssize_t error;
122         void *kvalue = NULL;
123         char kname[XATTR_NAME_MAX + 1];
124
125         error = strncpy_from_user(kname, name, sizeof(kname));
126         if (error == 0 || error == sizeof(kname))
127                 error = -ERANGE;
128         if (error < 0)
129                 return error;
130
131         if (size) {
132                 if (size > XATTR_SIZE_MAX)
133                         size = XATTR_SIZE_MAX;
134                 kvalue = kmalloc(size, GFP_KERNEL);
135                 if (!kvalue)
136                         return -ENOMEM;
137         }
138
139         error = -EOPNOTSUPP;
140         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);
145                 if (error > 0) {
146                         if (size && copy_to_user(value, kvalue, error))
147                                 error = -EFAULT;
148                 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
149                         /* The file system tried to returned a value bigger
150                            than XATTR_SIZE_MAX bytes. Not possible. */
151                         error = -E2BIG;
152                 }
153         }
154 out:
155         if (kvalue)
156                 kfree(kvalue);
157         return error;
158 }
159
160 asmlinkage ssize_t
161 sys_getxattr(char __user *path, char __user *name, void __user *value,
162              size_t size)
163 {
164         struct nameidata nd;
165         ssize_t error;
166
167         error = user_path_walk(path, &nd);
168         if (error)
169                 return error;
170         error = getxattr(nd.dentry, name, value, size);
171         path_release(&nd);
172         return error;
173 }
174
175 asmlinkage ssize_t
176 sys_lgetxattr(char __user *path, char __user *name, void __user *value,
177               size_t size)
178 {
179         struct nameidata nd;
180         ssize_t error;
181
182         error = user_path_walk_link(path, &nd);
183         if (error)
184                 return error;
185         error = getxattr(nd.dentry, name, value, size);
186         path_release(&nd);
187         return error;
188 }
189
190 asmlinkage ssize_t
191 sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
192 {
193         struct file *f;
194         ssize_t error = -EBADF;
195
196         f = fget(fd);
197         if (!f)
198                 return error;
199         error = getxattr(f->f_dentry, name, value, size);
200         fput(f);
201         return error;
202 }
203
204 /*
205  * Extended attribute LIST operations
206  */
207 static ssize_t
208 listxattr(struct dentry *d, char __user *list, size_t size)
209 {
210         ssize_t error;
211         char *klist = NULL;
212
213         if (size) {
214                 if (size > XATTR_LIST_MAX)
215                         size = XATTR_LIST_MAX;
216                 klist = kmalloc(size, GFP_KERNEL);
217                 if (!klist)
218                         return -ENOMEM;
219         }
220
221         error = -EOPNOTSUPP;
222         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);
227                 if (error > 0) {
228                         if (size && copy_to_user(list, klist, error))
229                                 error = -EFAULT;
230                 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
231                         /* The file system tried to returned a list bigger
232                            than XATTR_LIST_MAX bytes. Not possible. */
233                         error = -E2BIG;
234                 }
235         }
236 out:
237         if (klist)
238                 kfree(klist);
239         return error;
240 }
241
242 asmlinkage ssize_t
243 sys_listxattr(char __user *path, char __user *list, size_t size)
244 {
245         struct nameidata nd;
246         ssize_t error;
247
248         error = user_path_walk(path, &nd);
249         if (error)
250                 return error;
251         error = listxattr(nd.dentry, list, size);
252         path_release(&nd);
253         return error;
254 }
255
256 asmlinkage ssize_t
257 sys_llistxattr(char __user *path, char __user *list, size_t size)
258 {
259         struct nameidata nd;
260         ssize_t error;
261
262         error = user_path_walk_link(path, &nd);
263         if (error)
264                 return error;
265         error = listxattr(nd.dentry, list, size);
266         path_release(&nd);
267         return error;
268 }
269
270 asmlinkage ssize_t
271 sys_flistxattr(int fd, char __user *list, size_t size)
272 {
273         struct file *f;
274         ssize_t error = -EBADF;
275
276         f = fget(fd);
277         if (!f)
278                 return error;
279         error = listxattr(f->f_dentry, list, size);
280         fput(f);
281         return error;
282 }
283
284 /*
285  * Extended attribute REMOVE operations
286  */
287 static long
288 removexattr(struct dentry *d, char __user *name)
289 {
290         int error;
291         char kname[XATTR_NAME_MAX + 1];
292
293         error = strncpy_from_user(kname, name, sizeof(kname));
294         if (error == 0 || error == sizeof(kname))
295                 error = -ERANGE;
296         if (error < 0)
297                 return error;
298
299         error = -EOPNOTSUPP;
300         if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
301                 error = security_inode_removexattr(d, kname);
302                 if (error)
303                         goto out;
304                 down(&d->d_inode->i_sem);
305                 error = d->d_inode->i_op->removexattr(d, kname);
306                 up(&d->d_inode->i_sem);
307         }
308 out:
309         return error;
310 }
311
312 asmlinkage long
313 sys_removexattr(char __user *path, char __user *name)
314 {
315         struct nameidata nd;
316         int error;
317
318         error = user_path_walk(path, &nd);
319         if (error)
320                 return error;
321         error = removexattr(nd.dentry, name);
322         path_release(&nd);
323         return error;
324 }
325
326 asmlinkage long
327 sys_lremovexattr(char __user *path, char __user *name)
328 {
329         struct nameidata nd;
330         int error;
331
332         error = user_path_walk_link(path, &nd);
333         if (error)
334                 return error;
335         error = removexattr(nd.dentry, name);
336         path_release(&nd);
337         return error;
338 }
339
340 asmlinkage long
341 sys_fremovexattr(int fd, char __user *name)
342 {
343         struct file *f;
344         int error = -EBADF;
345
346         f = fget(fd);
347         if (!f)
348                 return error;
349         error = removexattr(f->f_dentry, name);
350         fput(f);
351         return error;
352 }
353
354
355 static const char *
356 strcmp_prefix(const char *a, const char *a_prefix)
357 {
358         while (*a_prefix && *a == *a_prefix) {
359                 a++;
360                 a_prefix++;
361         }
362         return *a_prefix ? NULL : a;
363 }
364
365 /*
366  * In order to implement different sets of xattr operations for each xattr
367  * prefix with the generic xattr API, a filesystem should create a
368  * null-terminated array of struct xattr_handler (one for each prefix) and
369  * hang a pointer to it off of the s_xattr field of the superblock.
370  *
371  * The generic_fooxattr() functions will use this list to dispatch xattr
372  * operations to the correct xattr_handler.
373  */
374 #define for_each_xattr_handler(handlers, handler)               \
375                 for ((handler) = *(handlers)++;                 \
376                         (handler) != NULL;                      \
377                         (handler) = *(handlers)++)
378
379 /*
380  * Find the xattr_handler with the matching prefix.
381  */
382 static struct xattr_handler *
383 xattr_resolve_name(struct xattr_handler **handlers, const char **name)
384 {
385         struct xattr_handler *handler;
386
387         if (!*name)
388                 return NULL;
389
390         for_each_xattr_handler(handlers, handler) {
391                 const char *n = strcmp_prefix(*name, handler->prefix);
392                 if (n) {
393                         *name = n;
394                         break;
395                 }
396         }
397         return handler;
398 }
399
400 /*
401  * Find the handler for the prefix and dispatch its get() operation.
402  */
403 ssize_t
404 generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
405 {
406         struct xattr_handler *handler;
407         struct inode *inode = dentry->d_inode;
408
409         handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
410         if (!handler)
411                 return -EOPNOTSUPP;
412         return handler->get(inode, name, buffer, size);
413 }
414
415 /*
416  * Combine the results of the list() operation from every xattr_handler in the
417  * list.
418  */
419 ssize_t
420 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
421 {
422         struct inode *inode = dentry->d_inode;
423         struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr;
424         unsigned int size = 0;
425
426         if (!buffer) {
427                 for_each_xattr_handler(handlers, handler)
428                         size += handler->list(inode, NULL, 0, NULL, 0);
429         } else {
430                 char *buf = buffer;
431
432                 for_each_xattr_handler(handlers, handler) {
433                         size = handler->list(inode, buf, buffer_size, NULL, 0);
434                         if (size > buffer_size)
435                                 return -ERANGE;
436                         buf += size;
437                         buffer_size -= size;
438                 }
439                 size = buf - buffer;
440         }
441         return size;
442 }
443
444 /*
445  * Find the handler for the prefix and dispatch its set() operation.
446  */
447 int
448 generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
449 {
450         struct xattr_handler *handler;
451         struct inode *inode = dentry->d_inode;
452
453         if (size == 0)
454                 value = "";  /* empty EA, do not remove */
455         handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
456         if (!handler)
457                 return -EOPNOTSUPP;
458         return handler->set(inode, name, value, size, flags);
459 }
460
461 /*
462  * Find the handler for the prefix and dispatch its set() operation to remove
463  * any associated extended attribute.
464  */
465 int
466 generic_removexattr(struct dentry *dentry, const char *name)
467 {
468         struct xattr_handler *handler;
469         struct inode *inode = dentry->d_inode;
470
471         handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
472         if (!handler)
473                 return -EOPNOTSUPP;
474         return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
475 }
476
477 EXPORT_SYMBOL(generic_getxattr);
478 EXPORT_SYMBOL(generic_listxattr);
479 EXPORT_SYMBOL(generic_setxattr);
480 EXPORT_SYMBOL(generic_removexattr);