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