Branch data Line data Source code
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/file.h>
13 : : #include <linux/xattr.h>
14 : : #include <linux/mount.h>
15 : : #include <linux/namei.h>
16 : : #include <linux/security.h>
17 : : #include <linux/evm.h>
18 : : #include <linux/syscalls.h>
19 : : #include <linux/export.h>
20 : : #include <linux/fsnotify.h>
21 : : #include <linux/audit.h>
22 : : #include <linux/vmalloc.h>
23 : : #include <linux/posix_acl_xattr.h>
24 : :
25 : : #include <asm/uaccess.h>
26 : :
27 : : /*
28 : : * Check permissions for extended attribute access. This is a bit complicated
29 : : * because different namespaces have very different rules.
30 : : */
31 : : static int
32 : 0 : xattr_permission(struct inode *inode, const char *name, int mask)
33 : : {
34 : : /*
35 : : * We can never set or remove an extended attribute on a read-only
36 : : * filesystem or on an immutable / append-only inode.
37 : : */
38 [ + + ]: 201 : if (mask & MAY_WRITE) {
39 [ + - ]: 2 : if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
40 : : return -EPERM;
41 : : }
42 : :
43 : : /*
44 : : * No restriction for security.* and system.* from the VFS. Decision
45 : : * on these is left to the underlying filesystem / security module.
46 : : */
47 [ + + ][ - + ]: 201 : if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
48 : 117 : !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
49 : : return 0;
50 : :
51 : : /*
52 : : * The trusted.* namespace can only be accessed by privileged users.
53 : : */
54 [ # # ]: 0 : if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
55 [ # # ]: 0 : if (!capable(CAP_SYS_ADMIN))
56 [ # # ]: 0 : return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
57 : : return 0;
58 : : }
59 : :
60 : : /*
61 : : * In the user.* namespace, only regular files and directories can have
62 : : * extended attributes. For sticky directories, only the owner and
63 : : * privileged users can write attributes.
64 : : */
65 [ # # ]: 0 : if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
66 [ # # ]: 0 : if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
67 [ # # ]: 0 : return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
68 [ # # ][ # # ]: 0 : if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
69 [ # # ]: 0 : (mask & MAY_WRITE) && !inode_owner_or_capable(inode))
70 : : return -EPERM;
71 : : }
72 : :
73 : 0 : return inode_permission(inode, mask);
74 : : }
75 : :
76 : : /**
77 : : * __vfs_setxattr_noperm - perform setxattr operation without performing
78 : : * permission checks.
79 : : *
80 : : * @dentry - object to perform setxattr on
81 : : * @name - xattr name to set
82 : : * @value - value to set @name to
83 : : * @size - size of @value
84 : : * @flags - flags to pass into filesystem operations
85 : : *
86 : : * returns the result of the internal setxattr or setsecurity operations.
87 : : *
88 : : * This function requires the caller to lock the inode's i_mutex before it
89 : : * is executed. It also assumes that the caller will make the appropriate
90 : : * permission checks.
91 : : */
92 : 0 : int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
93 : : const void *value, size_t size, int flags)
94 : : {
95 : 2 : struct inode *inode = dentry->d_inode;
96 : : int error = -EOPNOTSUPP;
97 : 2 : int issec = !strncmp(name, XATTR_SECURITY_PREFIX,
98 : : XATTR_SECURITY_PREFIX_LEN);
99 : :
100 [ - + ]: 2 : if (issec)
101 : 0 : inode->i_flags &= ~S_NOSEC;
102 [ + - ]: 2 : if (inode->i_op->setxattr) {
103 : 2 : error = inode->i_op->setxattr(dentry, name, value, size, flags);
104 [ - + ]: 2 : if (!error) {
105 : : fsnotify_xattr(dentry);
106 : 0 : security_inode_post_setxattr(dentry, name, value,
107 : : size, flags);
108 : : }
109 [ # # ]: 0 : } else if (issec) {
110 : 0 : const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
111 : 0 : error = security_inode_setsecurity(inode, suffix, value,
112 : : size, flags);
113 [ # # ]: 0 : if (!error)
114 : : fsnotify_xattr(dentry);
115 : : }
116 : :
117 : 2 : return error;
118 : : }
119 : :
120 : :
121 : : int
122 : 0 : vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
123 : : size_t size, int flags)
124 : : {
125 : 2 : struct inode *inode = dentry->d_inode;
126 : : int error;
127 : :
128 : 2 : error = xattr_permission(inode, name, MAY_WRITE);
129 [ + - ]: 2 : if (error)
130 : : return error;
131 : :
132 : 2 : mutex_lock(&inode->i_mutex);
133 : 2 : error = security_inode_setxattr(dentry, name, value, size, flags);
134 [ + - ]: 2 : if (error)
135 : : goto out;
136 : :
137 : 2 : error = __vfs_setxattr_noperm(dentry, name, value, size, flags);
138 : :
139 : : out:
140 : 2 : mutex_unlock(&inode->i_mutex);
141 : 2 : return error;
142 : : }
143 : : EXPORT_SYMBOL_GPL(vfs_setxattr);
144 : :
145 : : ssize_t
146 : 0 : xattr_getsecurity(struct inode *inode, const char *name, void *value,
147 : : size_t size)
148 : : {
149 : 84 : void *buffer = NULL;
150 : : ssize_t len;
151 : :
152 [ - + ]: 84 : if (!value || !size) {
153 : 0 : len = security_inode_getsecurity(inode, name, &buffer, false);
154 : 0 : goto out_noalloc;
155 : : }
156 : :
157 : 84 : len = security_inode_getsecurity(inode, name, &buffer, true);
158 [ - + ]: 84 : if (len < 0)
159 : : return len;
160 [ # # ]: 0 : if (size < len) {
161 : : len = -ERANGE;
162 : : goto out;
163 : : }
164 : 0 : memcpy(value, buffer, len);
165 : : out:
166 : 0 : security_release_secctx(buffer, len);
167 : : out_noalloc:
168 : 0 : return len;
169 : : }
170 : : EXPORT_SYMBOL_GPL(xattr_getsecurity);
171 : :
172 : : /*
173 : : * vfs_getxattr_alloc - allocate memory, if necessary, before calling getxattr
174 : : *
175 : : * Allocate memory, if not already allocated, or re-allocate correct size,
176 : : * before retrieving the extended attribute.
177 : : *
178 : : * Returns the result of alloc, if failed, or the getxattr operation.
179 : : */
180 : : ssize_t
181 : 0 : vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
182 : : size_t xattr_size, gfp_t flags)
183 : : {
184 : 0 : struct inode *inode = dentry->d_inode;
185 : 0 : char *value = *xattr_value;
186 : : int error;
187 : :
188 : 0 : error = xattr_permission(inode, name, MAY_READ);
189 [ # # ]: 0 : if (error)
190 : : return error;
191 : :
192 [ # # ]: 0 : if (!inode->i_op->getxattr)
193 : : return -EOPNOTSUPP;
194 : :
195 : 0 : error = inode->i_op->getxattr(dentry, name, NULL, 0);
196 [ # # ]: 0 : if (error < 0)
197 : : return error;
198 : :
199 [ # # ]: 0 : if (!value || (error > xattr_size)) {
200 : 0 : value = krealloc(*xattr_value, error + 1, flags);
201 [ # # ]: 0 : if (!value)
202 : : return -ENOMEM;
203 [ # # ]: 0 : memset(value, 0, error + 1);
204 : : }
205 : :
206 : 0 : error = inode->i_op->getxattr(dentry, name, value, error);
207 : 0 : *xattr_value = value;
208 : 0 : return error;
209 : : }
210 : :
211 : : /* Compare an extended attribute value with the given value */
212 : 0 : int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
213 : : const char *value, size_t size, gfp_t flags)
214 : : {
215 : 0 : char *xattr_value = NULL;
216 : : int rc;
217 : :
218 : 0 : rc = vfs_getxattr_alloc(dentry, xattr_name, &xattr_value, 0, flags);
219 [ # # ]: 0 : if (rc < 0)
220 : : return rc;
221 : :
222 [ # # ][ # # ]: 0 : if ((rc != size) || (memcmp(xattr_value, value, rc) != 0))
223 : : rc = -EINVAL;
224 : : else
225 : : rc = 0;
226 : 0 : kfree(xattr_value);
227 : 0 : return rc;
228 : : }
229 : :
230 : : ssize_t
231 : 0 : vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
232 : : {
233 : 199 : struct inode *inode = dentry->d_inode;
234 : : int error;
235 : :
236 : 199 : error = xattr_permission(inode, name, MAY_READ);
237 [ + - ]: 199 : if (error)
238 : : return error;
239 : :
240 : 199 : error = security_inode_getxattr(dentry, name);
241 [ + - ]: 199 : if (error)
242 : : return error;
243 : :
244 [ + + ]: 199 : if (!strncmp(name, XATTR_SECURITY_PREFIX,
245 : : XATTR_SECURITY_PREFIX_LEN)) {
246 : 84 : const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
247 : 84 : int ret = xattr_getsecurity(inode, suffix, value, size);
248 : : /*
249 : : * Only overwrite the return value if a security module
250 : : * is actually active.
251 : : */
252 [ + ]: 84 : if (ret == -EOPNOTSUPP)
253 : : goto nolsm;
254 : : return ret;
255 : : }
256 : : nolsm:
257 [ + - ]: 398 : if (inode->i_op->getxattr)
258 : 199 : error = inode->i_op->getxattr(dentry, name, value, size);
259 : : else
260 : : error = -EOPNOTSUPP;
261 : :
262 : 199 : return error;
263 : : }
264 : : EXPORT_SYMBOL_GPL(vfs_getxattr);
265 : :
266 : : ssize_t
267 : 0 : vfs_listxattr(struct dentry *d, char *list, size_t size)
268 : : {
269 : : ssize_t error;
270 : :
271 : 4 : error = security_inode_listxattr(d);
272 [ + - ]: 4 : if (error)
273 : : return error;
274 : : error = -EOPNOTSUPP;
275 [ + - ]: 4 : if (d->d_inode->i_op->listxattr) {
276 : 4 : error = d->d_inode->i_op->listxattr(d, list, size);
277 : : } else {
278 : 0 : error = security_inode_listsecurity(d->d_inode, list, size);
279 [ # # ]: 0 : if (size && error > size)
280 : : error = -ERANGE;
281 : : }
282 : 4 : return error;
283 : : }
284 : : EXPORT_SYMBOL_GPL(vfs_listxattr);
285 : :
286 : : int
287 : 0 : vfs_removexattr(struct dentry *dentry, const char *name)
288 : : {
289 : 0 : struct inode *inode = dentry->d_inode;
290 : : int error;
291 : :
292 [ # # ]: 0 : if (!inode->i_op->removexattr)
293 : : return -EOPNOTSUPP;
294 : :
295 : 0 : error = xattr_permission(inode, name, MAY_WRITE);
296 [ # # ]: 0 : if (error)
297 : : return error;
298 : :
299 : 0 : mutex_lock(&inode->i_mutex);
300 : 0 : error = security_inode_removexattr(dentry, name);
301 [ # # ]: 0 : if (error) {
302 : 0 : mutex_unlock(&inode->i_mutex);
303 : 0 : return error;
304 : : }
305 : :
306 : 0 : error = inode->i_op->removexattr(dentry, name);
307 : 0 : mutex_unlock(&inode->i_mutex);
308 : :
309 [ # # ]: 0 : if (!error) {
310 : : fsnotify_xattr(dentry);
311 : : evm_inode_post_removexattr(dentry, name);
312 : : }
313 : 0 : return error;
314 : : }
315 : : EXPORT_SYMBOL_GPL(vfs_removexattr);
316 : :
317 : :
318 : : /*
319 : : * Extended attribute SET operations
320 : : */
321 : : static long
322 : 0 : setxattr(struct dentry *d, const char __user *name, const void __user *value,
323 : : size_t size, int flags)
324 : : {
325 : : int error;
326 : : void *kvalue = NULL;
327 : : void *vvalue = NULL; /* If non-NULL, we used vmalloc() */
328 : : char kname[XATTR_NAME_MAX + 1];
329 : :
330 [ + - ]: 2 : if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
331 : : return -EINVAL;
332 : :
333 : 2 : error = strncpy_from_user(kname, name, sizeof(kname));
334 [ - + ]: 2 : if (error == 0 || error == sizeof(kname))
335 : : error = -ERANGE;
336 [ + - ]: 2 : if (error < 0)
337 : : return error;
338 : :
339 [ + - ]: 2 : if (size) {
340 [ + ]: 2 : if (size > XATTR_SIZE_MAX)
341 : : return -E2BIG;
342 : : kvalue = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
343 [ - + ]: 2 : if (!kvalue) {
344 : 0 : vvalue = vmalloc(size);
345 [ # # ]: 0 : if (!vvalue)
346 : : return -ENOMEM;
347 : : kvalue = vvalue;
348 : : }
349 [ + - ]: 2 : if (copy_from_user(kvalue, value, size)) {
350 : : error = -EFAULT;
351 : : goto out;
352 : : }
353 [ - + ][ # # ]: 2 : if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
354 : 0 : (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
355 : 2 : posix_acl_fix_xattr_from_user(kvalue, size);
356 : : }
357 : :
358 : 2 : error = vfs_setxattr(d, kname, kvalue, size, flags);
359 : : out:
360 [ - + ]: 2 : if (vvalue)
361 : 0 : vfree(vvalue);
362 : : else
363 : 2 : kfree(kvalue);
364 : 2 : return error;
365 : : }
366 : :
367 : 0 : SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
368 : : const char __user *, name, const void __user *, value,
369 : : size_t, size, int, flags)
370 : : {
371 : : struct path path;
372 : : int error;
373 : : unsigned int lookup_flags = LOOKUP_FOLLOW;
374 : : retry:
375 : 0 : error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
376 [ # # ]: 0 : if (error)
377 : : return error;
378 : 0 : error = mnt_want_write(path.mnt);
379 [ # # ]: 0 : if (!error) {
380 : 0 : error = setxattr(path.dentry, name, value, size, flags);
381 : 0 : mnt_drop_write(path.mnt);
382 : : }
383 : 0 : path_put(&path);
384 [ # # ]: 0 : if (retry_estale(error, lookup_flags)) {
385 : : lookup_flags |= LOOKUP_REVAL;
386 : : goto retry;
387 : : }
388 : : return error;
389 : : }
390 : :
391 : 0 : SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
392 : : const char __user *, name, const void __user *, value,
393 : : size_t, size, int, flags)
394 : : {
395 : : struct path path;
396 : : int error;
397 : : unsigned int lookup_flags = 0;
398 : : retry:
399 : 0 : error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
400 [ # # ]: 0 : if (error)
401 : : return error;
402 : 0 : error = mnt_want_write(path.mnt);
403 [ # # ]: 0 : if (!error) {
404 : 0 : error = setxattr(path.dentry, name, value, size, flags);
405 : 0 : mnt_drop_write(path.mnt);
406 : : }
407 : 0 : path_put(&path);
408 [ # # ]: 0 : if (retry_estale(error, lookup_flags)) {
409 : : lookup_flags |= LOOKUP_REVAL;
410 : : goto retry;
411 : : }
412 : : return error;
413 : : }
414 : :
415 : 0 : SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
416 : : const void __user *,value, size_t, size, int, flags)
417 : : {
418 : 2 : struct fd f = fdget(fd);
419 : : struct dentry *dentry;
420 : : int error = -EBADF;
421 : :
422 [ + - ]: 2 : if (!f.file)
423 : : return error;
424 : 2 : dentry = f.file->f_path.dentry;
425 : : audit_inode(NULL, dentry, 0);
426 : 2 : error = mnt_want_write_file(f.file);
427 [ + - ]: 2 : if (!error) {
428 : 2 : error = setxattr(dentry, name, value, size, flags);
429 : 2 : mnt_drop_write_file(f.file);
430 : : }
431 : : fdput(f);
432 : : return error;
433 : : }
434 : :
435 : : /*
436 : : * Extended attribute GET operations
437 : : */
438 : : static ssize_t
439 : 0 : getxattr(struct dentry *d, const char __user *name, void __user *value,
440 : : size_t size)
441 : : {
442 : : ssize_t error;
443 : : void *kvalue = NULL;
444 : : void *vvalue = NULL;
445 : : char kname[XATTR_NAME_MAX + 1];
446 : :
447 : 199 : error = strncpy_from_user(kname, name, sizeof(kname));
448 [ - + ]: 199 : if (error == 0 || error == sizeof(kname))
449 : : error = -ERANGE;
450 [ + - ]: 199 : if (error < 0)
451 : : return error;
452 : :
453 [ + ]: 199 : if (size) {
454 [ - + ]: 315 : if (size > XATTR_SIZE_MAX)
455 : : size = XATTR_SIZE_MAX;
456 : : kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
457 [ - + ]: 116 : if (!kvalue) {
458 : 0 : vvalue = vmalloc(size);
459 [ # # ]: 0 : if (!vvalue)
460 : : return -ENOMEM;
461 : : kvalue = vvalue;
462 : : }
463 : : }
464 : :
465 : 0 : error = vfs_getxattr(d, kname, kvalue, size);
466 [ - + ]: 199 : if (error > 0) {
467 [ # # ][ # # ]: 0 : if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
468 : 0 : (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
469 : 0 : posix_acl_fix_xattr_to_user(kvalue, size);
470 [ # # ][ # # ]: 0 : if (size && copy_to_user(value, kvalue, error))
471 : : error = -EFAULT;
472 [ - + ]: 199 : } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
473 : : /* The file system tried to returned a value bigger
474 : : than XATTR_SIZE_MAX bytes. Not possible. */
475 : : error = -E2BIG;
476 : : }
477 [ - + ]: 199 : if (vvalue)
478 : 0 : vfree(vvalue);
479 : : else
480 : 199 : kfree(kvalue);
481 : 199 : return error;
482 : : }
483 : :
484 : 98 : SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
485 : : const char __user *, name, void __user *, value, size_t, size)
486 : : {
487 : : struct path path;
488 : : ssize_t error;
489 : : unsigned int lookup_flags = LOOKUP_FOLLOW;
490 : : retry:
491 : 98 : error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
492 [ + - ]: 98 : if (error)
493 : : return error;
494 : 98 : error = getxattr(path.dentry, name, value, size);
495 : 98 : path_put(&path);
496 [ - - ]: 98 : if (retry_estale(error, lookup_flags)) {
497 : : lookup_flags |= LOOKUP_REVAL;
498 : : goto retry;
499 : : }
500 : : return error;
501 : : }
502 : :
503 : 84 : SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
504 : : const char __user *, name, void __user *, value, size_t, size)
505 : : {
506 : : struct path path;
507 : : ssize_t error;
508 : : unsigned int lookup_flags = 0;
509 : : retry:
510 : 84 : error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
511 [ + - ]: 84 : if (error)
512 : : return error;
513 : 84 : error = getxattr(path.dentry, name, value, size);
514 : 84 : path_put(&path);
515 [ - - ]: 84 : if (retry_estale(error, lookup_flags)) {
516 : : lookup_flags |= LOOKUP_REVAL;
517 : : goto retry;
518 : : }
519 : : return error;
520 : : }
521 : :
522 : 0 : SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
523 : : void __user *, value, size_t, size)
524 : : {
525 : 17 : struct fd f = fdget(fd);
526 : : ssize_t error = -EBADF;
527 : :
528 [ + - ]: 17 : if (!f.file)
529 : : return error;
530 : 17 : audit_inode(NULL, f.file->f_path.dentry, 0);
531 : 17 : error = getxattr(f.file->f_path.dentry, name, value, size);
532 : : fdput(f);
533 : : return error;
534 : : }
535 : :
536 : : /*
537 : : * Extended attribute LIST operations
538 : : */
539 : : static ssize_t
540 : 0 : listxattr(struct dentry *d, char __user *list, size_t size)
541 : : {
542 : : ssize_t error;
543 : : char *klist = NULL;
544 : : char *vlist = NULL; /* If non-NULL, we used vmalloc() */
545 : :
546 [ + ]: 4 : if (size) {
547 [ - + ]: 8 : if (size > XATTR_LIST_MAX)
548 : : size = XATTR_LIST_MAX;
549 : : klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL);
550 [ - + ]: 4 : if (!klist) {
551 : 0 : vlist = vmalloc(size);
552 [ # # ]: 0 : if (!vlist)
553 : : return -ENOMEM;
554 : : klist = vlist;
555 : : }
556 : : }
557 : :
558 : 0 : error = vfs_listxattr(d, klist, size);
559 [ - + ]: 4 : if (error > 0) {
560 [ # # ][ # # ]: 0 : if (size && copy_to_user(list, klist, error))
561 : : error = -EFAULT;
562 [ - + ]: 4 : } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
563 : : /* The file system tried to returned a list bigger
564 : : than XATTR_LIST_MAX bytes. Not possible. */
565 : : error = -E2BIG;
566 : : }
567 [ - + ]: 4 : if (vlist)
568 : 0 : vfree(vlist);
569 : : else
570 : 4 : kfree(klist);
571 : 4 : return error;
572 : : }
573 : :
574 : 2 : SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
575 : : size_t, size)
576 : : {
577 : : struct path path;
578 : : ssize_t error;
579 : : unsigned int lookup_flags = LOOKUP_FOLLOW;
580 : : retry:
581 : 2 : error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
582 [ + - ]: 2 : if (error)
583 : : return error;
584 : 2 : error = listxattr(path.dentry, list, size);
585 : 2 : path_put(&path);
586 [ - - ]: 2 : if (retry_estale(error, lookup_flags)) {
587 : : lookup_flags |= LOOKUP_REVAL;
588 : : goto retry;
589 : : }
590 : : return error;
591 : : }
592 : :
593 : 0 : SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
594 : : size_t, size)
595 : : {
596 : : struct path path;
597 : : ssize_t error;
598 : : unsigned int lookup_flags = 0;
599 : : retry:
600 : 0 : error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
601 [ # # ]: 0 : if (error)
602 : : return error;
603 : 0 : error = listxattr(path.dentry, list, size);
604 : 0 : path_put(&path);
605 [ # # ]: 0 : if (retry_estale(error, lookup_flags)) {
606 : : lookup_flags |= LOOKUP_REVAL;
607 : : goto retry;
608 : : }
609 : : return error;
610 : : }
611 : :
612 : 0 : SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
613 : : {
614 : 2 : struct fd f = fdget(fd);
615 : : ssize_t error = -EBADF;
616 : :
617 [ + - ]: 2 : if (!f.file)
618 : : return error;
619 : 2 : audit_inode(NULL, f.file->f_path.dentry, 0);
620 : 2 : error = listxattr(f.file->f_path.dentry, list, size);
621 : : fdput(f);
622 : : return error;
623 : : }
624 : :
625 : : /*
626 : : * Extended attribute REMOVE operations
627 : : */
628 : : static long
629 : 0 : removexattr(struct dentry *d, const char __user *name)
630 : : {
631 : : int error;
632 : : char kname[XATTR_NAME_MAX + 1];
633 : :
634 : 0 : error = strncpy_from_user(kname, name, sizeof(kname));
635 [ # # ]: 0 : if (error == 0 || error == sizeof(kname))
636 : : error = -ERANGE;
637 [ # # ]: 0 : if (error < 0)
638 : : return error;
639 : :
640 : 0 : return vfs_removexattr(d, kname);
641 : : }
642 : :
643 : 0 : SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
644 : : const char __user *, name)
645 : : {
646 : : struct path path;
647 : : int error;
648 : : unsigned int lookup_flags = LOOKUP_FOLLOW;
649 : : retry:
650 : 0 : error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
651 [ # # ]: 0 : if (error)
652 : : return error;
653 : 0 : error = mnt_want_write(path.mnt);
654 [ # # ]: 0 : if (!error) {
655 : 0 : error = removexattr(path.dentry, name);
656 : 0 : mnt_drop_write(path.mnt);
657 : : }
658 : 0 : path_put(&path);
659 [ # # ]: 0 : if (retry_estale(error, lookup_flags)) {
660 : : lookup_flags |= LOOKUP_REVAL;
661 : : goto retry;
662 : : }
663 : : return error;
664 : : }
665 : :
666 : 0 : SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
667 : : const char __user *, name)
668 : : {
669 : : struct path path;
670 : : int error;
671 : : unsigned int lookup_flags = 0;
672 : : retry:
673 : 0 : error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
674 [ # # ]: 0 : if (error)
675 : : return error;
676 : 0 : error = mnt_want_write(path.mnt);
677 [ # # ]: 0 : if (!error) {
678 : 0 : error = removexattr(path.dentry, name);
679 : 0 : mnt_drop_write(path.mnt);
680 : : }
681 : 0 : path_put(&path);
682 [ # # ]: 0 : if (retry_estale(error, lookup_flags)) {
683 : : lookup_flags |= LOOKUP_REVAL;
684 : : goto retry;
685 : : }
686 : : return error;
687 : : }
688 : :
689 : 0 : SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
690 : : {
691 : 0 : struct fd f = fdget(fd);
692 : : struct dentry *dentry;
693 : : int error = -EBADF;
694 : :
695 [ # # ]: 0 : if (!f.file)
696 : : return error;
697 : 0 : dentry = f.file->f_path.dentry;
698 : : audit_inode(NULL, dentry, 0);
699 : 0 : error = mnt_want_write_file(f.file);
700 [ # # ]: 0 : if (!error) {
701 : 0 : error = removexattr(dentry, name);
702 : 0 : mnt_drop_write_file(f.file);
703 : : }
704 : : fdput(f);
705 : : return error;
706 : : }
707 : :
708 : :
709 : : static const char *
710 : : strcmp_prefix(const char *a, const char *a_prefix)
711 : : {
712 [ + ][ - + ]: 102246 : while (*a_prefix && *a == *a_prefix) {
713 : 0 : a++;
714 : 0 : a_prefix++;
715 : : }
716 [ - + ]: 102246 : return *a_prefix ? NULL : a;
717 : : }
718 : :
719 : : /*
720 : : * In order to implement different sets of xattr operations for each xattr
721 : : * prefix with the generic xattr API, a filesystem should create a
722 : : * null-terminated array of struct xattr_handler (one for each prefix) and
723 : : * hang a pointer to it off of the s_xattr field of the superblock.
724 : : *
725 : : * The generic_fooxattr() functions will use this list to dispatch xattr
726 : : * operations to the correct xattr_handler.
727 : : */
728 : : #define for_each_xattr_handler(handlers, handler) \
729 : : for ((handler) = *(handlers)++; \
730 : : (handler) != NULL; \
731 : : (handler) = *(handlers)++)
732 : :
733 : : /*
734 : : * Find the xattr_handler with the matching prefix.
735 : : */
736 : : static const struct xattr_handler *
737 : 0 : xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
738 : : {
739 : : const struct xattr_handler *handler;
740 : :
741 [ + ]: 51259 : if (!*name)
742 : : return NULL;
743 : :
744 [ + + ]: 205013 : for_each_xattr_handler(handlers, handler) {
745 : 102246 : const char *n = strcmp_prefix(*name, handler->prefix);
746 [ + ]: 102246 : if (n) {
747 : 0 : *name = n;
748 : 0 : break;
749 : : }
750 : : }
751 : 51331 : return handler;
752 : : }
753 : :
754 : : /*
755 : : * Find the handler for the prefix and dispatch its get() operation.
756 : : */
757 : : ssize_t
758 : 0 : generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
759 : : {
760 : : const struct xattr_handler *handler;
761 : :
762 : 51269 : handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
763 [ - + ]: 51305 : if (!handler)
764 : : return -EOPNOTSUPP;
765 : 0 : return handler->get(dentry, name, buffer, size, handler->flags);
766 : : }
767 : :
768 : : /*
769 : : * Combine the results of the list() operation from every xattr_handler in the
770 : : * list.
771 : : */
772 : : ssize_t
773 : 0 : generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
774 : : {
775 : 0 : const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
776 : : unsigned int size = 0;
777 : :
778 [ # # ]: 0 : if (!buffer) {
779 [ # # ]: 0 : for_each_xattr_handler(handlers, handler) {
780 : 0 : size += handler->list(dentry, NULL, 0, NULL, 0,
781 : : handler->flags);
782 : : }
783 : : } else {
784 : : char *buf = buffer;
785 : :
786 [ # # ]: 0 : for_each_xattr_handler(handlers, handler) {
787 : 0 : size = handler->list(dentry, buf, buffer_size,
788 : : NULL, 0, handler->flags);
789 [ # # ]: 0 : if (size > buffer_size)
790 : : return -ERANGE;
791 : 0 : buf += size;
792 : 0 : buffer_size -= size;
793 : : }
794 : 0 : size = buf - buffer;
795 : : }
796 : 0 : return size;
797 : : }
798 : :
799 : : /*
800 : : * Find the handler for the prefix and dispatch its set() operation.
801 : : */
802 : : int
803 : 0 : generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
804 : : {
805 : : const struct xattr_handler *handler;
806 : :
807 [ - + ]: 2 : if (size == 0)
808 : : value = ""; /* empty EA, do not remove */
809 : 2 : handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
810 [ - + ]: 2 : if (!handler)
811 : : return -EOPNOTSUPP;
812 : 0 : return handler->set(dentry, name, value, size, flags, handler->flags);
813 : : }
814 : :
815 : : /*
816 : : * Find the handler for the prefix and dispatch its set() operation to remove
817 : : * any associated extended attribute.
818 : : */
819 : : int
820 : 0 : generic_removexattr(struct dentry *dentry, const char *name)
821 : : {
822 : : const struct xattr_handler *handler;
823 : :
824 : 0 : handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
825 [ # # ]: 0 : if (!handler)
826 : : return -EOPNOTSUPP;
827 : 0 : return handler->set(dentry, name, NULL, 0,
828 : : XATTR_REPLACE, handler->flags);
829 : : }
830 : :
831 : : EXPORT_SYMBOL(generic_getxattr);
832 : : EXPORT_SYMBOL(generic_listxattr);
833 : : EXPORT_SYMBOL(generic_setxattr);
834 : : EXPORT_SYMBOL(generic_removexattr);
835 : :
836 : : /*
837 : : * Allocate new xattr and copy in the value; but leave the name to callers.
838 : : */
839 : 0 : struct simple_xattr *simple_xattr_alloc(const void *value, size_t size)
840 : : {
841 : : struct simple_xattr *new_xattr;
842 : : size_t len;
843 : :
844 : : /* wrap around? */
845 : 0 : len = sizeof(*new_xattr) + size;
846 [ # # ]: 0 : if (len <= sizeof(*new_xattr))
847 : : return NULL;
848 : :
849 : : new_xattr = kmalloc(len, GFP_KERNEL);
850 [ # # ]: 0 : if (!new_xattr)
851 : : return NULL;
852 : :
853 : 0 : new_xattr->size = size;
854 : 0 : memcpy(new_xattr->value, value, size);
855 : 0 : return new_xattr;
856 : : }
857 : :
858 : : /*
859 : : * xattr GET operation for in-memory/pseudo filesystems
860 : : */
861 : 0 : int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
862 : : void *buffer, size_t size)
863 : : {
864 : : struct simple_xattr *xattr;
865 : : int ret = -ENODATA;
866 : :
867 : : spin_lock(&xattrs->lock);
868 [ - + ]: 461 : list_for_each_entry(xattr, &xattrs->head, list) {
869 [ # # ]: 0 : if (strcmp(name, xattr->name))
870 : 0 : continue;
871 : :
872 : 0 : ret = xattr->size;
873 [ # # ]: 0 : if (buffer) {
874 [ # # ]: 0 : if (size < xattr->size)
875 : : ret = -ERANGE;
876 : : else
877 : 0 : memcpy(buffer, xattr->value, xattr->size);
878 : : }
879 : : break;
880 : : }
881 : : spin_unlock(&xattrs->lock);
882 : 461 : return ret;
883 : : }
884 : :
885 : 0 : static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
886 : : const void *value, size_t size, int flags)
887 : : {
888 : : struct simple_xattr *xattr;
889 : : struct simple_xattr *new_xattr = NULL;
890 : : int err = 0;
891 : :
892 : : /* value == NULL means remove */
893 [ # # ]: 0 : if (value) {
894 : 0 : new_xattr = simple_xattr_alloc(value, size);
895 [ # # ]: 0 : if (!new_xattr)
896 : : return -ENOMEM;
897 : :
898 : 0 : new_xattr->name = kstrdup(name, GFP_KERNEL);
899 [ # # ]: 0 : if (!new_xattr->name) {
900 : 0 : kfree(new_xattr);
901 : 0 : return -ENOMEM;
902 : : }
903 : : }
904 : :
905 : : spin_lock(&xattrs->lock);
906 [ # # ]: 0 : list_for_each_entry(xattr, &xattrs->head, list) {
907 [ # # ]: 0 : if (!strcmp(name, xattr->name)) {
908 [ # # ]: 0 : if (flags & XATTR_CREATE) {
909 : : xattr = new_xattr;
910 : : err = -EEXIST;
911 [ # # ]: 0 : } else if (new_xattr) {
912 : 0 : list_replace(&xattr->list, &new_xattr->list);
913 : : } else {
914 : : list_del(&xattr->list);
915 : : }
916 : : goto out;
917 : : }
918 : : }
919 [ # # ]: 0 : if (flags & XATTR_REPLACE) {
920 : : xattr = new_xattr;
921 : : err = -ENODATA;
922 : : } else {
923 : 0 : list_add(&new_xattr->list, &xattrs->head);
924 : : xattr = NULL;
925 : : }
926 : : out:
927 : : spin_unlock(&xattrs->lock);
928 [ # # ]: 0 : if (xattr) {
929 : 0 : kfree(xattr->name);
930 : 0 : kfree(xattr);
931 : : }
932 : 0 : return err;
933 : :
934 : : }
935 : :
936 : : /**
937 : : * simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems
938 : : * @xattrs: target simple_xattr list
939 : : * @name: name of the new extended attribute
940 : : * @value: value of the new xattr. If %NULL, will remove the attribute
941 : : * @size: size of the new xattr
942 : : * @flags: %XATTR_{CREATE|REPLACE}
943 : : *
944 : : * %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
945 : : * with -EEXIST. If %XATTR_REPLACE is set, the xattr should exist;
946 : : * otherwise, fails with -ENODATA.
947 : : *
948 : : * Returns 0 on success, -errno on failure.
949 : : */
950 : 0 : int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
951 : : const void *value, size_t size, int flags)
952 : : {
953 [ # # ]: 0 : if (size == 0)
954 : : value = ""; /* empty EA, do not remove */
955 : 0 : return __simple_xattr_set(xattrs, name, value, size, flags);
956 : : }
957 : :
958 : : /*
959 : : * xattr REMOVE operation for in-memory/pseudo filesystems
960 : : */
961 : 0 : int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name)
962 : : {
963 : 0 : return __simple_xattr_set(xattrs, name, NULL, 0, XATTR_REPLACE);
964 : : }
965 : :
966 : : static bool xattr_is_trusted(const char *name)
967 : : {
968 : 0 : return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
969 : : }
970 : :
971 : : /*
972 : : * xattr LIST operation for in-memory/pseudo filesystems
973 : : */
974 : 0 : ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer,
975 : : size_t size)
976 : : {
977 : 0 : bool trusted = capable(CAP_SYS_ADMIN);
978 : : struct simple_xattr *xattr;
979 : : size_t used = 0;
980 : :
981 : : spin_lock(&xattrs->lock);
982 [ # # ]: 0 : list_for_each_entry(xattr, &xattrs->head, list) {
983 : : size_t len;
984 : :
985 : : /* skip "trusted." attributes for unprivileged callers */
986 [ # # ][ # # ]: 0 : if (!trusted && xattr_is_trusted(xattr->name))
987 : 0 : continue;
988 : :
989 : 0 : len = strlen(xattr->name) + 1;
990 : 0 : used += len;
991 [ # # ]: 0 : if (buffer) {
992 [ # # ]: 0 : if (size < used) {
993 : : used = -ERANGE;
994 : : break;
995 : : }
996 : 0 : memcpy(buffer, xattr->name, len);
997 : 0 : buffer += len;
998 : : }
999 : : }
1000 : : spin_unlock(&xattrs->lock);
1001 : :
1002 : 0 : return used;
1003 : : }
1004 : :
1005 : : /*
1006 : : * Adds an extended attribute to the list
1007 : : */
1008 : 0 : void simple_xattr_list_add(struct simple_xattrs *xattrs,
1009 : : struct simple_xattr *new_xattr)
1010 : : {
1011 : : spin_lock(&xattrs->lock);
1012 : 0 : list_add(&new_xattr->list, &xattrs->head);
1013 : : spin_unlock(&xattrs->lock);
1014 : 0 : }
|