[PATCH] Fix up 'linux-dvb' maintainers entry
[linux-2.6/history.git] / fs / xattr.c
blob175d3e817619dbdbc434365d06dd47374a981d63
1 /*
2 File: fs/xattr.c
4 Extended attribute handling.
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 */
9 #include <linux/fs.h>
10 #include <linux/slab.h>
11 #include <linux/smp_lock.h>
12 #include <linux/file.h>
13 #include <linux/xattr.h>
14 #include <linux/namei.h>
15 #include <linux/security.h>
16 #include <asm/uaccess.h>
19 * Extended attribute memory allocation wrappers, originally
20 * based on the Intermezzo PRESTO_ALLOC/PRESTO_FREE macros.
21 * Values larger than a page are uncommon - extended attributes
22 * are supposed to be small chunks of metadata, and it is quite
23 * unusual to have very many extended attributes, so lists tend
24 * to be quite short as well. The 64K upper limit is derived
25 * from the extended attribute size limit used by XFS.
26 * Intentionally allow zero @size for value/list size requests.
28 static void *
29 xattr_alloc(size_t size, size_t limit)
31 void *ptr;
33 if (size > limit)
34 return ERR_PTR(-E2BIG);
36 if (!size) /* size request, no buffer is needed */
37 return NULL;
39 ptr = kmalloc((unsigned long) size, GFP_KERNEL);
40 if (!ptr)
41 return ERR_PTR(-ENOMEM);
42 return ptr;
45 static void
46 xattr_free(void *ptr, size_t size)
48 if (size) /* for a size request, no buffer was needed */
49 kfree(ptr);
53 * Extended attribute SET operations
55 static long
56 setxattr(struct dentry *d, char __user *name, void __user *value,
57 size_t size, int flags)
59 int error;
60 void *kvalue;
61 char kname[XATTR_NAME_MAX + 1];
63 if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
64 return -EINVAL;
66 error = strncpy_from_user(kname, name, sizeof(kname));
67 if (error == 0 || error == sizeof(kname))
68 error = -ERANGE;
69 if (error < 0)
70 return error;
72 kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
73 if (IS_ERR(kvalue))
74 return PTR_ERR(kvalue);
76 if (size > 0 && copy_from_user(kvalue, value, size)) {
77 xattr_free(kvalue, size);
78 return -EFAULT;
81 error = -EOPNOTSUPP;
82 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
83 down(&d->d_inode->i_sem);
84 error = security_inode_setxattr(d, kname, kvalue, size, flags);
85 if (error)
86 goto out;
87 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
88 if (!error)
89 security_inode_post_setxattr(d, kname, kvalue, size, flags);
90 out:
91 up(&d->d_inode->i_sem);
93 xattr_free(kvalue, size);
94 return error;
97 asmlinkage long
98 sys_setxattr(char __user *path, char __user *name, void __user *value,
99 size_t size, int flags)
101 struct nameidata nd;
102 int error;
104 error = user_path_walk(path, &nd);
105 if (error)
106 return error;
107 error = setxattr(nd.dentry, name, value, size, flags);
108 path_release(&nd);
109 return error;
112 asmlinkage long
113 sys_lsetxattr(char __user *path, char __user *name, void __user *value,
114 size_t size, int flags)
116 struct nameidata nd;
117 int error;
119 error = user_path_walk_link(path, &nd);
120 if (error)
121 return error;
122 error = setxattr(nd.dentry, name, value, size, flags);
123 path_release(&nd);
124 return error;
127 asmlinkage long
128 sys_fsetxattr(int fd, char __user *name, void __user *value,
129 size_t size, int flags)
131 struct file *f;
132 int error = -EBADF;
134 f = fget(fd);
135 if (!f)
136 return error;
137 error = setxattr(f->f_dentry, name, value, size, flags);
138 fput(f);
139 return error;
143 * Extended attribute GET operations
145 static ssize_t
146 getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
148 ssize_t error;
149 void *kvalue;
150 char kname[XATTR_NAME_MAX + 1];
152 error = strncpy_from_user(kname, name, sizeof(kname));
153 if (error == 0 || error == sizeof(kname))
154 error = -ERANGE;
155 if (error < 0)
156 return error;
158 kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
159 if (IS_ERR(kvalue))
160 return PTR_ERR(kvalue);
162 error = -EOPNOTSUPP;
163 if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
164 error = security_inode_getxattr(d, kname);
165 if (error)
166 goto out;
167 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
170 if (kvalue && error > 0)
171 if (copy_to_user(value, kvalue, error))
172 error = -EFAULT;
173 out:
174 xattr_free(kvalue, size);
175 return error;
178 asmlinkage ssize_t
179 sys_getxattr(char __user *path, char __user *name, void __user *value,
180 size_t size)
182 struct nameidata nd;
183 ssize_t error;
185 error = user_path_walk(path, &nd);
186 if (error)
187 return error;
188 error = getxattr(nd.dentry, name, value, size);
189 path_release(&nd);
190 return error;
193 asmlinkage ssize_t
194 sys_lgetxattr(char __user *path, char __user *name, void __user *value,
195 size_t size)
197 struct nameidata nd;
198 ssize_t error;
200 error = user_path_walk_link(path, &nd);
201 if (error)
202 return error;
203 error = getxattr(nd.dentry, name, value, size);
204 path_release(&nd);
205 return error;
208 asmlinkage ssize_t
209 sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
211 struct file *f;
212 ssize_t error = -EBADF;
214 f = fget(fd);
215 if (!f)
216 return error;
217 error = getxattr(f->f_dentry, name, value, size);
218 fput(f);
219 return error;
223 * Extended attribute LIST operations
225 static ssize_t
226 listxattr(struct dentry *d, char __user *list, size_t size)
228 ssize_t error;
229 char *klist;
231 klist = (char *)xattr_alloc(size, XATTR_LIST_MAX);
232 if (IS_ERR(klist))
233 return PTR_ERR(klist);
235 error = -EOPNOTSUPP;
236 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
237 error = security_inode_listxattr(d);
238 if (error)
239 goto out;
240 error = d->d_inode->i_op->listxattr(d, klist, size);
243 if (klist && error > 0)
244 if (copy_to_user(list, klist, error))
245 error = -EFAULT;
246 out:
247 xattr_free(klist, size);
248 return error;
251 asmlinkage ssize_t
252 sys_listxattr(char __user *path, char __user *list, size_t size)
254 struct nameidata nd;
255 ssize_t error;
257 error = user_path_walk(path, &nd);
258 if (error)
259 return error;
260 error = listxattr(nd.dentry, list, size);
261 path_release(&nd);
262 return error;
265 asmlinkage ssize_t
266 sys_llistxattr(char __user *path, char __user *list, size_t size)
268 struct nameidata nd;
269 ssize_t error;
271 error = user_path_walk_link(path, &nd);
272 if (error)
273 return error;
274 error = listxattr(nd.dentry, list, size);
275 path_release(&nd);
276 return error;
279 asmlinkage ssize_t
280 sys_flistxattr(int fd, char __user *list, size_t size)
282 struct file *f;
283 ssize_t error = -EBADF;
285 f = fget(fd);
286 if (!f)
287 return error;
288 error = listxattr(f->f_dentry, list, size);
289 fput(f);
290 return error;
294 * Extended attribute REMOVE operations
296 static long
297 removexattr(struct dentry *d, char __user *name)
299 int error;
300 char kname[XATTR_NAME_MAX + 1];
302 error = strncpy_from_user(kname, name, sizeof(kname));
303 if (error == 0 || error == sizeof(kname))
304 error = -ERANGE;
305 if (error < 0)
306 return error;
308 error = -EOPNOTSUPP;
309 if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
310 error = security_inode_removexattr(d, kname);
311 if (error)
312 goto out;
313 down(&d->d_inode->i_sem);
314 error = d->d_inode->i_op->removexattr(d, kname);
315 up(&d->d_inode->i_sem);
317 out:
318 return error;
321 asmlinkage long
322 sys_removexattr(char __user *path, char __user *name)
324 struct nameidata nd;
325 int error;
327 error = user_path_walk(path, &nd);
328 if (error)
329 return error;
330 error = removexattr(nd.dentry, name);
331 path_release(&nd);
332 return error;
335 asmlinkage long
336 sys_lremovexattr(char __user *path, char __user *name)
338 struct nameidata nd;
339 int error;
341 error = user_path_walk_link(path, &nd);
342 if (error)
343 return error;
344 error = removexattr(nd.dentry, name);
345 path_release(&nd);
346 return error;
349 asmlinkage long
350 sys_fremovexattr(int fd, char __user *name)
352 struct file *f;
353 int error = -EBADF;
355 f = fget(fd);
356 if (!f)
357 return error;
358 error = removexattr(f->f_dentry, name);
359 fput(f);
360 return error;