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