Wipe out the last remains of arch/mips64/boot, rot in pieces ...
[linux-2.6/linux-mips.git] / fs / xattr.c
blob37d2a109eef7a810fef435ea079794366dc78b4b
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 *name, void *value, size_t size, int flags)
58 int error;
59 void *kvalue;
60 char kname[XATTR_NAME_MAX + 1];
62 if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
63 return -EINVAL;
65 error = strncpy_from_user(kname, name, sizeof(kname));
66 if (error == 0 || error == sizeof(kname))
67 error = -ERANGE;
68 if (error < 0)
69 return error;
71 kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
72 if (IS_ERR(kvalue))
73 return PTR_ERR(kvalue);
75 if (size > 0 && copy_from_user(kvalue, value, size)) {
76 xattr_free(kvalue, size);
77 return -EFAULT;
80 error = -EOPNOTSUPP;
81 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
82 down(&d->d_inode->i_sem);
83 error = security_inode_setxattr(d, kname, kvalue, size, flags);
84 if (error)
85 goto out;
86 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
87 if (!error)
88 security_inode_post_setxattr(d, kname, kvalue, size, flags);
89 out:
90 up(&d->d_inode->i_sem);
92 xattr_free(kvalue, size);
93 return error;
96 asmlinkage long
97 sys_setxattr(char *path, char *name, void *value, size_t size, int flags)
99 struct nameidata nd;
100 int error;
102 error = user_path_walk(path, &nd);
103 if (error)
104 return error;
105 error = setxattr(nd.dentry, name, value, size, flags);
106 path_release(&nd);
107 return error;
110 asmlinkage long
111 sys_lsetxattr(char *path, char *name, void *value, size_t size, int flags)
113 struct nameidata nd;
114 int error;
116 error = user_path_walk_link(path, &nd);
117 if (error)
118 return error;
119 error = setxattr(nd.dentry, name, value, size, flags);
120 path_release(&nd);
121 return error;
124 asmlinkage long
125 sys_fsetxattr(int fd, char *name, void *value, size_t size, int flags)
127 struct file *f;
128 int error = -EBADF;
130 f = fget(fd);
131 if (!f)
132 return error;
133 error = setxattr(f->f_dentry, name, value, size, flags);
134 fput(f);
135 return error;
139 * Extended attribute GET operations
141 static ssize_t
142 getxattr(struct dentry *d, char *name, void *value, size_t size)
144 ssize_t error;
145 void *kvalue;
146 char kname[XATTR_NAME_MAX + 1];
148 error = strncpy_from_user(kname, name, sizeof(kname));
149 if (error == 0 || error == sizeof(kname))
150 error = -ERANGE;
151 if (error < 0)
152 return error;
154 kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
155 if (IS_ERR(kvalue))
156 return PTR_ERR(kvalue);
158 error = -EOPNOTSUPP;
159 if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
160 error = security_inode_getxattr(d, kname);
161 if (error)
162 goto out;
163 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
166 if (kvalue && error > 0)
167 if (copy_to_user(value, kvalue, error))
168 error = -EFAULT;
169 out:
170 xattr_free(kvalue, size);
171 return error;
174 asmlinkage ssize_t
175 sys_getxattr(char *path, char *name, void *value, size_t size)
177 struct nameidata nd;
178 ssize_t error;
180 error = user_path_walk(path, &nd);
181 if (error)
182 return error;
183 error = getxattr(nd.dentry, name, value, size);
184 path_release(&nd);
185 return error;
188 asmlinkage ssize_t
189 sys_lgetxattr(char *path, char *name, void *value, size_t size)
191 struct nameidata nd;
192 ssize_t error;
194 error = user_path_walk_link(path, &nd);
195 if (error)
196 return error;
197 error = getxattr(nd.dentry, name, value, size);
198 path_release(&nd);
199 return error;
202 asmlinkage ssize_t
203 sys_fgetxattr(int fd, char *name, void *value, size_t size)
205 struct file *f;
206 ssize_t error = -EBADF;
208 f = fget(fd);
209 if (!f)
210 return error;
211 error = getxattr(f->f_dentry, name, value, size);
212 fput(f);
213 return error;
217 * Extended attribute LIST operations
219 static ssize_t
220 listxattr(struct dentry *d, char *list, size_t size)
222 ssize_t error;
223 char *klist;
225 klist = (char *)xattr_alloc(size, XATTR_LIST_MAX);
226 if (IS_ERR(klist))
227 return PTR_ERR(klist);
229 error = -EOPNOTSUPP;
230 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
231 error = security_inode_listxattr(d);
232 if (error)
233 goto out;
234 error = d->d_inode->i_op->listxattr(d, klist, size);
237 if (klist && error > 0)
238 if (copy_to_user(list, klist, error))
239 error = -EFAULT;
240 out:
241 xattr_free(klist, size);
242 return error;
245 asmlinkage ssize_t
246 sys_listxattr(char *path, char *list, size_t size)
248 struct nameidata nd;
249 ssize_t error;
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;
259 asmlinkage ssize_t
260 sys_llistxattr(char *path, char *list, size_t size)
262 struct nameidata nd;
263 ssize_t error;
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;
273 asmlinkage ssize_t
274 sys_flistxattr(int fd, char *list, size_t size)
276 struct file *f;
277 ssize_t error = -EBADF;
279 f = fget(fd);
280 if (!f)
281 return error;
282 error = listxattr(f->f_dentry, list, size);
283 fput(f);
284 return error;
288 * Extended attribute REMOVE operations
290 static long
291 removexattr(struct dentry *d, char *name)
293 int error;
294 char kname[XATTR_NAME_MAX + 1];
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;
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);
311 out:
312 return error;
315 asmlinkage long
316 sys_removexattr(char *path, char *name)
318 struct nameidata nd;
319 int error;
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;
329 asmlinkage long
330 sys_lremovexattr(char *path, char *name)
332 struct nameidata nd;
333 int error;
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;
343 asmlinkage long
344 sys_fremovexattr(int fd, char *name)
346 struct file *f;
347 int error = -EBADF;
349 f = fget(fd);
350 if (!f)
351 return error;
352 error = removexattr(f->f_dentry, name);
353 fput(f);
354 return error;