xref: /openbmc/linux/fs/xattr.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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);
481