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