457c899653991 (Thomas Gleixner 2019-05-19 13:08:55 +0100 1) // SPDX-License-Identifier: GPL-2.0-only
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) File: fs/xattr.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) Extended attribute handling.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) #include <linux/fs.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) #include <linux/slab.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) #include <linux/file.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include <linux/xattr.h>
18f335aff8691 (Dave Hansen 2008-02-15 14:37:38 -0800 15) #include <linux/mount.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) #include <linux/namei.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) #include <linux/security.h>
c7b87de23b6fd (Mimi Zohar 2011-03-09 14:39:18 -0500 18) #include <linux/evm.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 19) #include <linux/syscalls.h>
630d9c47274aa (Paul Gortmaker 2011-11-16 23:57:37 -0500 20) #include <linux/export.h>
0eeca28300df1 (Robert Love 2005-07-12 17:06:03 -0400 21) #include <linux/fsnotify.h>
73241ccca0f77 (Amy Griffis 2005-11-03 16:00:25 +0000 22) #include <linux/audit.h>
0d08d7b7e13b5 (Andrew Morton 2012-04-05 14:25:07 -0700 23) #include <linux/vmalloc.h>
2f6f0654ab619 (Eric W. Biederman 2012-02-07 18:52:57 -0800 24) #include <linux/posix_acl_xattr.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25)
7c0f6ba682b9c (Linus Torvalds 2016-12-24 11:46:01 -0800 26) #include <linux/uaccess.h>
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 27)
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 28) static const char *
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 29) strcmp_prefix(const char *a, const char *a_prefix)
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 30) {
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 31) while (*a_prefix && *a == *a_prefix) {
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 32) a++;
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 33) a_prefix++;
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 34) }
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 35) return *a_prefix ? NULL : a;
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 36) }
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 37)
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 38) /*
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 39) * In order to implement different sets of xattr operations for each xattr
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 40) * prefix, a filesystem should create a null-terminated array of struct
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 41) * xattr_handler (one for each prefix) and hang a pointer to it off of the
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 42) * s_xattr field of the superblock.
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 43) */
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 44) #define for_each_xattr_handler(handlers, handler) \
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 45) if (handlers) \
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 46) for ((handler) = *(handlers)++; \
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 47) (handler) != NULL; \
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 48) (handler) = *(handlers)++)
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 49)
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 50) /*
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 51) * Find the xattr_handler with the matching prefix.
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 52) */
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 53) static const struct xattr_handler *
d0a5b995a3083 (Andreas Gruenbacher 2016-09-29 17:48:39 +0200 54) xattr_resolve_name(struct inode *inode, const char **name)
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 55) {
d0a5b995a3083 (Andreas Gruenbacher 2016-09-29 17:48:39 +0200 56) const struct xattr_handler **handlers = inode->i_sb->s_xattr;
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 57) const struct xattr_handler *handler;
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 58)
5f6e59ae8277c (Andreas Gruenbacher 2016-09-29 17:48:40 +0200 59) if (!(inode->i_opflags & IOP_XATTR)) {
5f6e59ae8277c (Andreas Gruenbacher 2016-09-29 17:48:40 +0200 60) if (unlikely(is_bad_inode(inode)))
5f6e59ae8277c (Andreas Gruenbacher 2016-09-29 17:48:40 +0200 61) return ERR_PTR(-EIO);
d0a5b995a3083 (Andreas Gruenbacher 2016-09-29 17:48:39 +0200 62) return ERR_PTR(-EOPNOTSUPP);
5f6e59ae8277c (Andreas Gruenbacher 2016-09-29 17:48:40 +0200 63) }
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 64) for_each_xattr_handler(handlers, handler) {
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 65) const char *n;
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 66)
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 67) n = strcmp_prefix(*name, xattr_prefix(handler));
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 68) if (n) {
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 69) if (!handler->prefix ^ !*n) {
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 70) if (*n)
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 71) continue;
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 72) return ERR_PTR(-EINVAL);
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 73) }
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 74) *name = n;
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 75) return handler;
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 76) }
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 77) }
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 78) return ERR_PTR(-EOPNOTSUPP);
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 79) }
b6ba11773d953 (Andreas Gruenbacher 2016-09-29 17:48:38 +0200 80)
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 81) /*
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 82) * Check permissions for extended attribute access. This is a bit complicated
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 83) * because different namespaces have very different rules.
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 84) */
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 85) static int
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 86) xattr_permission(struct user_namespace *mnt_userns, struct inode *inode,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 87) const char *name, int mask)
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 88) {
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 89) /*
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 90) * We can never set or remove an extended attribute on a read-only
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 91) * filesystem or on an immutable / append-only inode.
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 92) */
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 93) if (mask & MAY_WRITE) {
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 94) if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 95) return -EPERM;
0bd23d09b874e (Eric W. Biederman 2016-06-29 14:54:46 -0500 96) /*
0bd23d09b874e (Eric W. Biederman 2016-06-29 14:54:46 -0500 97) * Updating an xattr will likely cause i_uid and i_gid
0bd23d09b874e (Eric W. Biederman 2016-06-29 14:54:46 -0500 98) * to be writen back improperly if their true value is
0bd23d09b874e (Eric W. Biederman 2016-06-29 14:54:46 -0500 99) * unknown to the vfs.
0bd23d09b874e (Eric W. Biederman 2016-06-29 14:54:46 -0500 100) */
ba73d98745be1 (Christian Brauner 2021-01-21 14:19:31 +0100 101) if (HAS_UNMAPPED_ID(mnt_userns, inode))
0bd23d09b874e (Eric W. Biederman 2016-06-29 14:54:46 -0500 102) return -EPERM;
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 103) }
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 104)
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 105) /*
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 106) * No restriction for security.* and system.* from the VFS. Decision
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 107) * on these is left to the underlying filesystem / security module.
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 108) */
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 109) if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 110) !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 111) return 0;
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 112)
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 113) /*
55b23bde19c08 (Andreas Gruenbacher 2011-05-27 14:50:36 +0200 114) * The trusted.* namespace can only be accessed by privileged users.
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 115) */
55b23bde19c08 (Andreas Gruenbacher 2011-05-27 14:50:36 +0200 116) if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
55b23bde19c08 (Andreas Gruenbacher 2011-05-27 14:50:36 +0200 117) if (!capable(CAP_SYS_ADMIN))
55b23bde19c08 (Andreas Gruenbacher 2011-05-27 14:50:36 +0200 118) return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
55b23bde19c08 (Andreas Gruenbacher 2011-05-27 14:50:36 +0200 119) return 0;
55b23bde19c08 (Andreas Gruenbacher 2011-05-27 14:50:36 +0200 120) }
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 121)
55b23bde19c08 (Andreas Gruenbacher 2011-05-27 14:50:36 +0200 122) /*
55b23bde19c08 (Andreas Gruenbacher 2011-05-27 14:50:36 +0200 123) * In the user.* namespace, only regular files and directories can have
f1f2d8713d16a (Andreas Gruenbacher 2006-11-02 22:07:29 -0800 124) * extended attributes. For sticky directories, only the owner and
55b23bde19c08 (Andreas Gruenbacher 2011-05-27 14:50:36 +0200 125) * privileged users can write attributes.
f1f2d8713d16a (Andreas Gruenbacher 2006-11-02 22:07:29 -0800 126) */
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 127) if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
f1f2d8713d16a (Andreas Gruenbacher 2006-11-02 22:07:29 -0800 128) if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
55b23bde19c08 (Andreas Gruenbacher 2011-05-27 14:50:36 +0200 129) return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
f1f2d8713d16a (Andreas Gruenbacher 2006-11-02 22:07:29 -0800 130) if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
21cb47be6fb9e (Christian Brauner 2021-01-21 14:19:25 +0100 131) (mask & MAY_WRITE) &&
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 132) !inode_owner_or_capable(mnt_userns, inode))
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 133) return -EPERM;
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 134) }
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 135)
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 136) return inode_permission(mnt_userns, inode, mask);
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 137) }
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 138)
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 139) /*
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 140) * Look for any handler that deals with the specified namespace.
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 141) */
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 142) int
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 143) xattr_supported_namespace(struct inode *inode, const char *prefix)
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 144) {
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 145) const struct xattr_handler **handlers = inode->i_sb->s_xattr;
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 146) const struct xattr_handler *handler;
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 147) size_t preflen;
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 148)
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 149) if (!(inode->i_opflags & IOP_XATTR)) {
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 150) if (unlikely(is_bad_inode(inode)))
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 151) return -EIO;
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 152) return -EOPNOTSUPP;
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 153) }
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 154)
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 155) preflen = strlen(prefix);
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 156)
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 157) for_each_xattr_handler(handlers, handler) {
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 158) if (!strncmp(xattr_prefix(handler), prefix, preflen))
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 159) return 0;
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 160) }
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 161)
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 162) return -EOPNOTSUPP;
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 163) }
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 164) EXPORT_SYMBOL(xattr_supported_namespace);
cab8d289c5ad5 (Frank van der Linden 2020-06-23 22:39:19 +0000 165)
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 166) int
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 167) __vfs_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 168) struct inode *inode, const char *name, const void *value,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 169) size_t size, int flags)
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 170) {
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 171) const struct xattr_handler *handler;
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 172)
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 173) handler = xattr_resolve_name(inode, &name);
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 174) if (IS_ERR(handler))
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 175) return PTR_ERR(handler);
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 176) if (!handler->set)
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 177) return -EOPNOTSUPP;
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 178) if (size == 0)
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 179) value = ""; /* empty EA, do not remove */
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 180) return handler->set(handler, mnt_userns, dentry, inode, name, value,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 181) size, flags);
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 182) }
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 183) EXPORT_SYMBOL(__vfs_setxattr);
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 184)
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 185) /**
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 186) * __vfs_setxattr_noperm - perform setxattr operation without performing
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 187) * permission checks.
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 188) *
6961fed420146 (Randy Dunlap 2021-02-15 20:29:29 -0800 189) * @mnt_userns: user namespace of the mount the inode was found from
6961fed420146 (Randy Dunlap 2021-02-15 20:29:29 -0800 190) * @dentry: object to perform setxattr on
6961fed420146 (Randy Dunlap 2021-02-15 20:29:29 -0800 191) * @name: xattr name to set
6961fed420146 (Randy Dunlap 2021-02-15 20:29:29 -0800 192) * @value: value to set @name to
6961fed420146 (Randy Dunlap 2021-02-15 20:29:29 -0800 193) * @size: size of @value
6961fed420146 (Randy Dunlap 2021-02-15 20:29:29 -0800 194) * @flags: flags to pass into filesystem operations
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 195) *
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 196) * returns the result of the internal setxattr or setsecurity operations.
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 197) *
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 198) * This function requires the caller to lock the inode's i_mutex before it
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 199) * is executed. It also assumes that the caller will make the appropriate
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 200) * permission checks.
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 201) */
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 202) int __vfs_setxattr_noperm(struct user_namespace *mnt_userns,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 203) struct dentry *dentry, const char *name,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 204) const void *value, size_t size, int flags)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 205) {
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 206) struct inode *inode = dentry->d_inode;
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 207) int error = -EAGAIN;
69b4573296469 (Andi Kleen 2011-05-28 08:25:51 -0700 208) int issec = !strncmp(name, XATTR_SECURITY_PREFIX,
69b4573296469 (Andi Kleen 2011-05-28 08:25:51 -0700 209) XATTR_SECURITY_PREFIX_LEN);
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 210)
69b4573296469 (Andi Kleen 2011-05-28 08:25:51 -0700 211) if (issec)
69b4573296469 (Andi Kleen 2011-05-28 08:25:51 -0700 212) inode->i_flags &= ~S_NOSEC;
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 213) if (inode->i_opflags & IOP_XATTR) {
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 214) error = __vfs_setxattr(mnt_userns, dentry, inode, name, value,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 215) size, flags);
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 216) if (!error) {
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 217) fsnotify_xattr(dentry);
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 218) security_inode_post_setxattr(dentry, name, value,
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 219) size, flags);
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 220) }
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 221) } else {
5f6e59ae8277c (Andreas Gruenbacher 2016-09-29 17:48:40 +0200 222) if (unlikely(is_bad_inode(inode)))
5f6e59ae8277c (Andreas Gruenbacher 2016-09-29 17:48:40 +0200 223) return -EIO;
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 224) }
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 225) if (error == -EAGAIN) {
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 226) error = -EOPNOTSUPP;
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 227)
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 228) if (issec) {
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 229) const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 230)
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 231) error = security_inode_setsecurity(inode, suffix, value,
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 232) size, flags);
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 233) if (!error)
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 234) fsnotify_xattr(dentry);
4a59015372840 (Andreas Gruenbacher 2016-11-13 21:23:34 +0100 235) }
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 236) }
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 237)
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 238) return error;
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 239) }
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 240)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 241) /**
da5c1c0bb316e (Randy Dunlap 2020-10-13 16:48:27 -0700 242) * __vfs_setxattr_locked - set an extended attribute while holding the inode
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 243) * lock
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 244) *
6961fed420146 (Randy Dunlap 2021-02-15 20:29:29 -0800 245) * @mnt_userns: user namespace of the mount of the target inode
da5c1c0bb316e (Randy Dunlap 2020-10-13 16:48:27 -0700 246) * @dentry: object to perform setxattr on
da5c1c0bb316e (Randy Dunlap 2020-10-13 16:48:27 -0700 247) * @name: xattr name to set
da5c1c0bb316e (Randy Dunlap 2020-10-13 16:48:27 -0700 248) * @value: value to set @name to
da5c1c0bb316e (Randy Dunlap 2020-10-13 16:48:27 -0700 249) * @size: size of @value
da5c1c0bb316e (Randy Dunlap 2020-10-13 16:48:27 -0700 250) * @flags: flags to pass into filesystem operations
da5c1c0bb316e (Randy Dunlap 2020-10-13 16:48:27 -0700 251) * @delegated_inode: on return, will contain an inode pointer that
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 252) * a delegation was broken on, NULL if none.
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 253) */
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 254) int
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 255) __vfs_setxattr_locked(struct user_namespace *mnt_userns, struct dentry *dentry,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 256) const char *name, const void *value, size_t size,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 257) int flags, struct inode **delegated_inode)
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 258) {
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 259) struct inode *inode = dentry->d_inode;
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 260) int error;
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 261)
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 262) error = xattr_permission(mnt_userns, inode, name, MAY_WRITE);
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 263) if (error)
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 264) return error;
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 265)
71bc356f93a1c (Christian Brauner 2021-01-21 14:19:29 +0100 266) error = security_inode_setxattr(mnt_userns, dentry, name, value, size,
71bc356f93a1c (Christian Brauner 2021-01-21 14:19:29 +0100 267) flags);
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 268) if (error)
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 269) goto out;
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 270)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 271) error = try_break_deleg(inode, delegated_inode);
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 272) if (error)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 273) goto out;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 274)
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 275) error = __vfs_setxattr_noperm(mnt_userns, dentry, name, value,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 276) size, flags);
b1ab7e4b2a88d (David P. Quigley 2009-09-03 14:25:56 -0400 277)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 278) out:
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 279) return error;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 280) }
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 281) EXPORT_SYMBOL_GPL(__vfs_setxattr_locked);
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 282)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 283) int
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 284) vfs_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 285) const char *name, const void *value, size_t size, int flags)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 286) {
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 287) struct inode *inode = dentry->d_inode;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 288) struct inode *delegated_inode = NULL;
7c03e2cda4a58 (Miklos Szeredi 2020-12-14 15:26:13 +0100 289) const void *orig_value = value;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 290) int error;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 291)
7c03e2cda4a58 (Miklos Szeredi 2020-12-14 15:26:13 +0100 292) if (size && strcmp(name, XATTR_NAME_CAPS) == 0) {
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 293) error = cap_convert_nscap(mnt_userns, dentry, &value, size);
7c03e2cda4a58 (Miklos Szeredi 2020-12-14 15:26:13 +0100 294) if (error < 0)
7c03e2cda4a58 (Miklos Szeredi 2020-12-14 15:26:13 +0100 295) return error;
7c03e2cda4a58 (Miklos Szeredi 2020-12-14 15:26:13 +0100 296) size = error;
7c03e2cda4a58 (Miklos Szeredi 2020-12-14 15:26:13 +0100 297) }
7c03e2cda4a58 (Miklos Szeredi 2020-12-14 15:26:13 +0100 298)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 299) retry_deleg:
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 300) inode_lock(inode);
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 301) error = __vfs_setxattr_locked(mnt_userns, dentry, name, value, size,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 302) flags, &delegated_inode);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 303) inode_unlock(inode);
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 304)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 305) if (delegated_inode) {
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 306) error = break_deleg_wait(&delegated_inode);
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 307) if (!error)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 308) goto retry_deleg;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 309) }
7c03e2cda4a58 (Miklos Szeredi 2020-12-14 15:26:13 +0100 310) if (value != orig_value)
7c03e2cda4a58 (Miklos Szeredi 2020-12-14 15:26:13 +0100 311) kfree(value);
7c03e2cda4a58 (Miklos Szeredi 2020-12-14 15:26:13 +0100 312)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 313) return error;
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 314) }
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 315) EXPORT_SYMBOL_GPL(vfs_setxattr);
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 316)
2220c5b0a7fb7 (Al Viro 2018-04-24 21:22:04 -0400 317) static ssize_t
71bc356f93a1c (Christian Brauner 2021-01-21 14:19:29 +0100 318) xattr_getsecurity(struct user_namespace *mnt_userns, struct inode *inode,
71bc356f93a1c (Christian Brauner 2021-01-21 14:19:29 +0100 319) const char *name, void *value, size_t size)
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 320) {
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 321) void *buffer = NULL;
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 322) ssize_t len;
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 323)
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 324) if (!value || !size) {
71bc356f93a1c (Christian Brauner 2021-01-21 14:19:29 +0100 325) len = security_inode_getsecurity(mnt_userns, inode, name,
71bc356f93a1c (Christian Brauner 2021-01-21 14:19:29 +0100 326) &buffer, false);
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 327) goto out_noalloc;
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 328) }
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 329)
71bc356f93a1c (Christian Brauner 2021-01-21 14:19:29 +0100 330) len = security_inode_getsecurity(mnt_userns, inode, name, &buffer,
71bc356f93a1c (Christian Brauner 2021-01-21 14:19:29 +0100 331) true);
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 332) if (len < 0)
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 333) return len;
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 334) if (size < len) {
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 335) len = -ERANGE;
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 336) goto out;
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 337) }
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 338) memcpy(value, buffer, len);
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 339) out:
57e7ba04d422c (Casey Schaufler 2017-09-19 09:39:08 -0700 340) kfree(buffer);
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 341) out_noalloc:
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 342) return len;
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 343) }
42492594043d6 (David P. Quigley 2008-02-04 22:29:39 -0800 344)
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 345) /*
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 346) * vfs_getxattr_alloc - allocate memory, if necessary, before calling getxattr
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 347) *
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 348) * Allocate memory, if not already allocated, or re-allocate correct size,
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 349) * before retrieving the extended attribute.
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 350) *
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 351) * Returns the result of alloc, if failed, or the getxattr operation.
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 352) */
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 353) ssize_t
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 354) vfs_getxattr_alloc(struct user_namespace *mnt_userns, struct dentry *dentry,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 355) const char *name, char **xattr_value, size_t xattr_size,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 356) gfp_t flags)
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 357) {
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 358) const struct xattr_handler *handler;
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 359) struct inode *inode = dentry->d_inode;
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 360) char *value = *xattr_value;
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 361) int error;
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 362)
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 363) error = xattr_permission(mnt_userns, inode, name, MAY_READ);
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 364) if (error)
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 365) return error;
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 366)
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 367) handler = xattr_resolve_name(inode, &name);
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 368) if (IS_ERR(handler))
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 369) return PTR_ERR(handler);
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 370) if (!handler->get)
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 371) return -EOPNOTSUPP;
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 372) error = handler->get(handler, dentry, inode, name, NULL, 0);
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 373) if (error < 0)
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 374) return error;
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 375)
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 376) if (!value || (error > xattr_size)) {
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 377) value = krealloc(*xattr_value, error + 1, flags);
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 378) if (!value)
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 379) return -ENOMEM;
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 380) memset(value, 0, error + 1);
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 381) }
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 382)
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 383) error = handler->get(handler, dentry, inode, name, value, error);
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 384) *xattr_value = value;
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 385) return error;
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 386) }
1601fbad2b14e (Mimi Zohar 2011-03-09 14:23:34 -0500 387)
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 388) ssize_t
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 389) __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 390) void *value, size_t size)
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 391) {
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 392) const struct xattr_handler *handler;
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 393)
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 394) handler = xattr_resolve_name(inode, &name);
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 395) if (IS_ERR(handler))
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 396) return PTR_ERR(handler);
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 397) if (!handler->get)
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 398) return -EOPNOTSUPP;
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 399) return handler->get(handler, dentry, inode, name, value, size);
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 400) }
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 401) EXPORT_SYMBOL(__vfs_getxattr);
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 402)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 403) ssize_t
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 404) vfs_getxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 405) const char *name, void *value, size_t size)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 406) {
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 407) struct inode *inode = dentry->d_inode;
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 408) int error;
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 409)
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 410) error = xattr_permission(mnt_userns, inode, name, MAY_READ);
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 411) if (error)
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 412) return error;
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 413)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 414) error = security_inode_getxattr(dentry, name);
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 415) if (error)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 416) return error;
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 417)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 418) if (!strncmp(name, XATTR_SECURITY_PREFIX,
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 419) XATTR_SECURITY_PREFIX_LEN)) {
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 420) const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
71bc356f93a1c (Christian Brauner 2021-01-21 14:19:29 +0100 421) int ret = xattr_getsecurity(mnt_userns, inode, suffix, value,
71bc356f93a1c (Christian Brauner 2021-01-21 14:19:29 +0100 422) size);
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 423) /*
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 424) * Only overwrite the return value if a security module
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 425) * is actually active.
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 426) */
4bea58053f206 (David P. Quigley 2008-02-04 22:29:40 -0800 427) if (ret == -EOPNOTSUPP)
4bea58053f206 (David P. Quigley 2008-02-04 22:29:40 -0800 428) goto nolsm;
4bea58053f206 (David P. Quigley 2008-02-04 22:29:40 -0800 429) return ret;
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 430) }
4bea58053f206 (David P. Quigley 2008-02-04 22:29:40 -0800 431) nolsm:
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 432) return __vfs_getxattr(dentry, inode, name, value, size);
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 433) }
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 434) EXPORT_SYMBOL_GPL(vfs_getxattr);
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 435)
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 436) ssize_t
bf3ee71363c0b (Andreas Gruenbacher 2016-09-29 17:48:43 +0200 437) vfs_listxattr(struct dentry *dentry, char *list, size_t size)
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 438) {
bf3ee71363c0b (Andreas Gruenbacher 2016-09-29 17:48:43 +0200 439) struct inode *inode = d_inode(dentry);
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 440) ssize_t error;
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 441)
bf3ee71363c0b (Andreas Gruenbacher 2016-09-29 17:48:43 +0200 442) error = security_inode_listxattr(dentry);
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 443) if (error)
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 444) return error;
bf3ee71363c0b (Andreas Gruenbacher 2016-09-29 17:48:43 +0200 445) if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
bf3ee71363c0b (Andreas Gruenbacher 2016-09-29 17:48:43 +0200 446) error = inode->i_op->listxattr(dentry, list, size);
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 447) } else {
bf3ee71363c0b (Andreas Gruenbacher 2016-09-29 17:48:43 +0200 448) error = security_inode_listsecurity(inode, list, size);
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 449) if (size && error > size)
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 450) error = -ERANGE;
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 451) }
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 452) return error;
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 453) }
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 454) EXPORT_SYMBOL_GPL(vfs_listxattr);
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 455)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 456) int
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 457) __vfs_removexattr(struct user_namespace *mnt_userns, struct dentry *dentry,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 458) const char *name)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 459) {
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 460) struct inode *inode = d_inode(dentry);
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 461) const struct xattr_handler *handler;
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 462)
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 463) handler = xattr_resolve_name(inode, &name);
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 464) if (IS_ERR(handler))
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 465) return PTR_ERR(handler);
6c6ef9f26e598 (Andreas Gruenbacher 2016-09-29 17:48:44 +0200 466) if (!handler->set)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 467) return -EOPNOTSUPP;
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 468) return handler->set(handler, mnt_userns, dentry, inode, name, NULL, 0,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 469) XATTR_REPLACE);
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 470) }
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 471) EXPORT_SYMBOL(__vfs_removexattr);
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 472)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 473) /**
da5c1c0bb316e (Randy Dunlap 2020-10-13 16:48:27 -0700 474) * __vfs_removexattr_locked - set an extended attribute while holding the inode
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 475) * lock
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 476) *
6961fed420146 (Randy Dunlap 2021-02-15 20:29:29 -0800 477) * @mnt_userns: user namespace of the mount of the target inode
da5c1c0bb316e (Randy Dunlap 2020-10-13 16:48:27 -0700 478) * @dentry: object to perform setxattr on
da5c1c0bb316e (Randy Dunlap 2020-10-13 16:48:27 -0700 479) * @name: name of xattr to remove
da5c1c0bb316e (Randy Dunlap 2020-10-13 16:48:27 -0700 480) * @delegated_inode: on return, will contain an inode pointer that
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 481) * a delegation was broken on, NULL if none.
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 482) */
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 483) int
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 484) __vfs_removexattr_locked(struct user_namespace *mnt_userns,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 485) struct dentry *dentry, const char *name,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 486) struct inode **delegated_inode)
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 487) {
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 488) struct inode *inode = dentry->d_inode;
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 489) int error;
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 490)
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 491) error = xattr_permission(mnt_userns, inode, name, MAY_WRITE);
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 492) if (error)
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 493) return error;
e0ad7b073eb73 (akpm@osdl.org 2006-01-09 20:51:56 -0800 494)
71bc356f93a1c (Christian Brauner 2021-01-21 14:19:29 +0100 495) error = security_inode_removexattr(mnt_userns, dentry, name);
7c51bb00c40e5 (Dmitry Kasatkin 2014-11-20 16:31:01 +0200 496) if (error)
7c51bb00c40e5 (Dmitry Kasatkin 2014-11-20 16:31:01 +0200 497) goto out;
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 498)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 499) error = try_break_deleg(inode, delegated_inode);
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 500) if (error)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 501) goto out;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 502)
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 503) error = __vfs_removexattr(mnt_userns, dentry, name);
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 504)
c7b87de23b6fd (Mimi Zohar 2011-03-09 14:39:18 -0500 505) if (!error) {
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 506) fsnotify_xattr(dentry);
c7b87de23b6fd (Mimi Zohar 2011-03-09 14:39:18 -0500 507) evm_inode_post_removexattr(dentry, name);
c7b87de23b6fd (Mimi Zohar 2011-03-09 14:39:18 -0500 508) }
7c51bb00c40e5 (Dmitry Kasatkin 2014-11-20 16:31:01 +0200 509)
7c51bb00c40e5 (Dmitry Kasatkin 2014-11-20 16:31:01 +0200 510) out:
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 511) return error;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 512) }
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 513) EXPORT_SYMBOL_GPL(__vfs_removexattr_locked);
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 514)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 515) int
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 516) vfs_removexattr(struct user_namespace *mnt_userns, struct dentry *dentry,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 517) const char *name)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 518) {
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 519) struct inode *inode = dentry->d_inode;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 520) struct inode *delegated_inode = NULL;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 521) int error;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 522)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 523) retry_deleg:
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 524) inode_lock(inode);
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 525) error = __vfs_removexattr_locked(mnt_userns, dentry,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 526) name, &delegated_inode);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 527) inode_unlock(inode);
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 528)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 529) if (delegated_inode) {
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 530) error = break_deleg_wait(&delegated_inode);
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 531) if (!error)
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 532) goto retry_deleg;
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 533) }
08b5d5014a27e (Frank van der Linden 2020-06-23 22:39:18 +0000 534)
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 535) return error;
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 536) }
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 537) EXPORT_SYMBOL_GPL(vfs_removexattr);
5be196e5f925d (Christoph Hellwig 2006-01-09 20:51:55 -0800 538)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 539) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 540) * Extended attribute SET operations
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 541) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 542) static long
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 543) setxattr(struct user_namespace *mnt_userns, struct dentry *d,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 544) const char __user *name, const void __user *value, size_t size,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 545) int flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 546) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 547) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 548) void *kvalue = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 549) char kname[XATTR_NAME_MAX + 1];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 550)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 551) if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 552) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 553)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 554) error = strncpy_from_user(kname, name, sizeof(kname));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 555) if (error == 0 || error == sizeof(kname))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 556) error = -ERANGE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 557) if (error < 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 558) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 559)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 560) if (size) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 561) if (size > XATTR_SIZE_MAX)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 562) return -E2BIG;
752ade68cbd81 (Michal Hocko 2017-05-08 15:57:27 -0700 563) kvalue = kvmalloc(size, GFP_KERNEL);
752ade68cbd81 (Michal Hocko 2017-05-08 15:57:27 -0700 564) if (!kvalue)
752ade68cbd81 (Michal Hocko 2017-05-08 15:57:27 -0700 565) return -ENOMEM;
44c824982fd37 (Andrew Morton 2012-04-05 14:25:07 -0700 566) if (copy_from_user(kvalue, value, size)) {
44c824982fd37 (Andrew Morton 2012-04-05 14:25:07 -0700 567) error = -EFAULT;
44c824982fd37 (Andrew Morton 2012-04-05 14:25:07 -0700 568) goto out;
44c824982fd37 (Andrew Morton 2012-04-05 14:25:07 -0700 569) }
2f6f0654ab619 (Eric W. Biederman 2012-02-07 18:52:57 -0800 570) if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
2f6f0654ab619 (Eric W. Biederman 2012-02-07 18:52:57 -0800 571) (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 572) posix_acl_fix_xattr_from_user(mnt_userns, kvalue, size);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 573) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 574)
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 575) error = vfs_setxattr(mnt_userns, d, kname, kvalue, size, flags);
44c824982fd37 (Andrew Morton 2012-04-05 14:25:07 -0700 576) out:
0b2a6f231dcbc (Richard Weinberger 2016-01-02 23:09:47 +0100 577) kvfree(kvalue);
0b2a6f231dcbc (Richard Weinberger 2016-01-02 23:09:47 +0100 578)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 579) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 580) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 581)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 582) static int path_setxattr(const char __user *pathname,
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 583) const char __user *name, const void __user *value,
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 584) size_t size, int flags, unsigned int lookup_flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 585) {
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 586) struct path path;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 587) int error;
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 588)
68f1bb8bb89e0 (Jeff Layton 2012-12-11 12:10:15 -0500 589) retry:
68f1bb8bb89e0 (Jeff Layton 2012-12-11 12:10:15 -0500 590) error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 591) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 592) return error;
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 593) error = mnt_want_write(path.mnt);
18f335aff8691 (Dave Hansen 2008-02-15 14:37:38 -0800 594) if (!error) {
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 595) error = setxattr(mnt_user_ns(path.mnt), path.dentry, name,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 596) value, size, flags);
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 597) mnt_drop_write(path.mnt);
18f335aff8691 (Dave Hansen 2008-02-15 14:37:38 -0800 598) }
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 599) path_put(&path);
68f1bb8bb89e0 (Jeff Layton 2012-12-11 12:10:15 -0500 600) if (retry_estale(error, lookup_flags)) {
68f1bb8bb89e0 (Jeff Layton 2012-12-11 12:10:15 -0500 601) lookup_flags |= LOOKUP_REVAL;
68f1bb8bb89e0 (Jeff Layton 2012-12-11 12:10:15 -0500 602) goto retry;
68f1bb8bb89e0 (Jeff Layton 2012-12-11 12:10:15 -0500 603) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 604) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 605) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 606)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 607) SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 608) const char __user *, name, const void __user *, value,
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 609) size_t, size, int, flags)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 610) {
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 611) return path_setxattr(pathname, name, value, size, flags, LOOKUP_FOLLOW);
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 612) }
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 613)
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 614) SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 615) const char __user *, name, const void __user *, value,
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 616) size_t, size, int, flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 617) {
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 618) return path_setxattr(pathname, name, value, size, flags, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 619) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 620)
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 621) SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 622) const void __user *,value, size_t, size, int, flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 623) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 624) struct fd f = fdget(fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 625) int error = -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 626)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 627) if (!f.file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 628) return error;
9f45f5bf302da (Al Viro 2014-10-31 17:44:57 -0400 629) audit_file(f.file);
6742cee043532 (Miklos Szeredi 2018-07-18 15:44:43 +0200 630) error = mnt_want_write_file(f.file);
18f335aff8691 (Dave Hansen 2008-02-15 14:37:38 -0800 631) if (!error) {
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 632) error = setxattr(file_mnt_user_ns(f.file),
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 633) f.file->f_path.dentry, name,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 634) value, size, flags);
6742cee043532 (Miklos Szeredi 2018-07-18 15:44:43 +0200 635) mnt_drop_write_file(f.file);
18f335aff8691 (Dave Hansen 2008-02-15 14:37:38 -0800 636) }
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 637) fdput(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 638) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 639) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 640)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 641) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 642) * Extended attribute GET operations
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 643) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 644) static ssize_t
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 645) getxattr(struct user_namespace *mnt_userns, struct dentry *d,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 646) const char __user *name, void __user *value, size_t size)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 647) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 648) ssize_t error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 649) void *kvalue = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 650) char kname[XATTR_NAME_MAX + 1];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 651)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 652) error = strncpy_from_user(kname, name, sizeof(kname));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 653) if (error == 0 || error == sizeof(kname))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 654) error = -ERANGE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 655) if (error < 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 656) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 657)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 658) if (size) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 659) if (size > XATTR_SIZE_MAX)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 660) size = XATTR_SIZE_MAX;
752ade68cbd81 (Michal Hocko 2017-05-08 15:57:27 -0700 661) kvalue = kvzalloc(size, GFP_KERNEL);
752ade68cbd81 (Michal Hocko 2017-05-08 15:57:27 -0700 662) if (!kvalue)
752ade68cbd81 (Michal Hocko 2017-05-08 15:57:27 -0700 663) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 664) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 665)
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 666) error = vfs_getxattr(mnt_userns, d, kname, kvalue, size);
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 667) if (error > 0) {
2f6f0654ab619 (Eric W. Biederman 2012-02-07 18:52:57 -0800 668) if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
2f6f0654ab619 (Eric W. Biederman 2012-02-07 18:52:57 -0800 669) (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 670) posix_acl_fix_xattr_to_user(mnt_userns, kvalue, error);
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 671) if (size && copy_to_user(value, kvalue, error))
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 672) error = -EFAULT;
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 673) } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 674) /* The file system tried to returned a value bigger
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 675) than XATTR_SIZE_MAX bytes. Not possible. */
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 676) error = -E2BIG;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 677) }
0b2a6f231dcbc (Richard Weinberger 2016-01-02 23:09:47 +0100 678)
0b2a6f231dcbc (Richard Weinberger 2016-01-02 23:09:47 +0100 679) kvfree(kvalue);
0b2a6f231dcbc (Richard Weinberger 2016-01-02 23:09:47 +0100 680)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 681) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 682) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 683)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 684) static ssize_t path_getxattr(const char __user *pathname,
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 685) const char __user *name, void __user *value,
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 686) size_t size, unsigned int lookup_flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 687) {
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 688) struct path path;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 689) ssize_t error;
60e66b48ca208 (Jeff Layton 2012-12-11 12:10:16 -0500 690) retry:
60e66b48ca208 (Jeff Layton 2012-12-11 12:10:16 -0500 691) error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 692) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 693) return error;
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 694) error = getxattr(mnt_user_ns(path.mnt), path.dentry, name, value, size);
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 695) path_put(&path);
60e66b48ca208 (Jeff Layton 2012-12-11 12:10:16 -0500 696) if (retry_estale(error, lookup_flags)) {
60e66b48ca208 (Jeff Layton 2012-12-11 12:10:16 -0500 697) lookup_flags |= LOOKUP_REVAL;
60e66b48ca208 (Jeff Layton 2012-12-11 12:10:16 -0500 698) goto retry;
60e66b48ca208 (Jeff Layton 2012-12-11 12:10:16 -0500 699) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 700) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 701) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 702)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 703) SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 704) const char __user *, name, void __user *, value, size_t, size)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 705) {
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 706) return path_getxattr(pathname, name, value, size, LOOKUP_FOLLOW);
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 707) }
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 708)
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 709) SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 710) const char __user *, name, void __user *, value, size_t, size)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 711) {
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 712) return path_getxattr(pathname, name, value, size, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 713) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 714)
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 715) SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 716) void __user *, value, size_t, size)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 717) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 718) struct fd f = fdget(fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 719) ssize_t error = -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 720)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 721) if (!f.file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 722) return error;
9f45f5bf302da (Al Viro 2014-10-31 17:44:57 -0400 723) audit_file(f.file);
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 724) error = getxattr(file_mnt_user_ns(f.file), f.file->f_path.dentry,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 725) name, value, size);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 726) fdput(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 727) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 728) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 729)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 730) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 731) * Extended attribute LIST operations
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 732) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 733) static ssize_t
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 734) listxattr(struct dentry *d, char __user *list, size_t size)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 735) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 736) ssize_t error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 737) char *klist = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 738)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 739) if (size) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 740) if (size > XATTR_LIST_MAX)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 741) size = XATTR_LIST_MAX;
752ade68cbd81 (Michal Hocko 2017-05-08 15:57:27 -0700 742) klist = kvmalloc(size, GFP_KERNEL);
752ade68cbd81 (Michal Hocko 2017-05-08 15:57:27 -0700 743) if (!klist)
752ade68cbd81 (Michal Hocko 2017-05-08 15:57:27 -0700 744) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 745) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 746)
659564c8adfe1 (Bill Nottingham 2006-10-09 16:10:48 -0400 747) error = vfs_listxattr(d, klist, size);
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 748) if (error > 0) {
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 749) if (size && copy_to_user(list, klist, error))
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 750) error = -EFAULT;
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 751) } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 752) /* The file system tried to returned a list bigger
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 753) than XATTR_LIST_MAX bytes. Not possible. */
f549d6c18c0e8 (Stephen Smalley 2005-09-03 15:55:18 -0700 754) error = -E2BIG;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 755) }
0b2a6f231dcbc (Richard Weinberger 2016-01-02 23:09:47 +0100 756)
0b2a6f231dcbc (Richard Weinberger 2016-01-02 23:09:47 +0100 757) kvfree(klist);
0b2a6f231dcbc (Richard Weinberger 2016-01-02 23:09:47 +0100 758)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 759) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 760) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 761)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 762) static ssize_t path_listxattr(const char __user *pathname, char __user *list,
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 763) size_t size, unsigned int lookup_flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 764) {
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 765) struct path path;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 766) ssize_t error;
10a90cf36efe0 (Jeff Layton 2012-12-11 12:10:16 -0500 767) retry:
10a90cf36efe0 (Jeff Layton 2012-12-11 12:10:16 -0500 768) error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 769) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 770) return error;
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 771) error = listxattr(path.dentry, list, size);
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 772) path_put(&path);
10a90cf36efe0 (Jeff Layton 2012-12-11 12:10:16 -0500 773) if (retry_estale(error, lookup_flags)) {
10a90cf36efe0 (Jeff Layton 2012-12-11 12:10:16 -0500 774) lookup_flags |= LOOKUP_REVAL;
10a90cf36efe0 (Jeff Layton 2012-12-11 12:10:16 -0500 775) goto retry;
10a90cf36efe0 (Jeff Layton 2012-12-11 12:10:16 -0500 776) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 777) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 778) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 779)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 780) SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 781) size_t, size)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 782) {
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 783) return path_listxattr(pathname, list, size, LOOKUP_FOLLOW);
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 784) }
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 785)
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 786) SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 787) size_t, size)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 788) {
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 789) return path_listxattr(pathname, list, size, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 790) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 791)
64fd1de3d8216 (Heiko Carstens 2009-01-14 14:14:14 +0100 792) SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 793) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 794) struct fd f = fdget(fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 795) ssize_t error = -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 796)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 797) if (!f.file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 798) return error;
9f45f5bf302da (Al Viro 2014-10-31 17:44:57 -0400 799) audit_file(f.file);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 800) error = listxattr(f.file->f_path.dentry, list, size);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 801) fdput(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 802) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 803) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 804)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 805) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 806) * Extended attribute REMOVE operations
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 807) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 808) static long
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 809) removexattr(struct user_namespace *mnt_userns, struct dentry *d,
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 810) const char __user *name)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 811) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 812) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 813) char kname[XATTR_NAME_MAX + 1];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 814)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 815) error = strncpy_from_user(kname, name, sizeof(kname));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 816) if (error == 0 || error == sizeof(kname))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 817) error = -ERANGE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 818) if (error < 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 819) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 820)
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 821) return vfs_removexattr(mnt_userns, d, kname);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 822) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 823)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 824) static int path_removexattr(const char __user *pathname,
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 825) const char __user *name, unsigned int lookup_flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 826) {
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 827) struct path path;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 828) int error;
12f0621299040 (Jeff Layton 2012-12-11 12:10:17 -0500 829) retry:
12f0621299040 (Jeff Layton 2012-12-11 12:10:17 -0500 830) error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 831) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 832) return error;
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 833) error = mnt_want_write(path.mnt);
18f335aff8691 (Dave Hansen 2008-02-15 14:37:38 -0800 834) if (!error) {
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 835) error = removexattr(mnt_user_ns(path.mnt), path.dentry, name);
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 836) mnt_drop_write(path.mnt);
18f335aff8691 (Dave Hansen 2008-02-15 14:37:38 -0800 837) }
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 838) path_put(&path);
12f0621299040 (Jeff Layton 2012-12-11 12:10:17 -0500 839) if (retry_estale(error, lookup_flags)) {
12f0621299040 (Jeff Layton 2012-12-11 12:10:17 -0500 840) lookup_flags |= LOOKUP_REVAL;
12f0621299040 (Jeff Layton 2012-12-11 12:10:17 -0500 841) goto retry;
12f0621299040 (Jeff Layton 2012-12-11 12:10:17 -0500 842) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 843) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 844) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 845)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 846) SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 847) const char __user *, name)
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 848) {
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 849) return path_removexattr(pathname, name, LOOKUP_FOLLOW);
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 850) }
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 851)
6a6160a7b5c27 (Heiko Carstens 2009-01-14 14:14:15 +0100 852) SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
6a6160a7b5c27 (Heiko Carstens 2009-01-14 14:14:15 +0100 853) const char __user *, name)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 854) {
8cc431165d8fb (Eric Biggers 2014-10-12 11:59:58 -0500 855) return path_removexattr(pathname, name, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 856) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 857)
6a6160a7b5c27 (Heiko Carstens 2009-01-14 14:14:15 +0100 858) SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 859) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 860) struct fd f = fdget(fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 861) int error = -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 862)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 863) if (!f.file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 864) return error;
9f45f5bf302da (Al Viro 2014-10-31 17:44:57 -0400 865) audit_file(f.file);
6742cee043532 (Miklos Szeredi 2018-07-18 15:44:43 +0200 866) error = mnt_want_write_file(f.file);
18f335aff8691 (Dave Hansen 2008-02-15 14:37:38 -0800 867) if (!error) {
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 868) error = removexattr(file_mnt_user_ns(f.file),
c7c7a1a18af4c (Tycho Andersen 2021-01-21 14:19:28 +0100 869) f.file->f_path.dentry, name);
6742cee043532 (Miklos Szeredi 2018-07-18 15:44:43 +0200 870) mnt_drop_write_file(f.file);
18f335aff8691 (Dave Hansen 2008-02-15 14:37:38 -0800 871) }
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 872) fdput(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 873) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 874) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 875)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 876) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 877) * Combine the results of the list() operation from every xattr_handler in the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 878) * list.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 879) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 880) ssize_t
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 881) generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 882) {
bb4354538eb7b (Stephen Hemminger 2010-05-13 17:53:14 -0700 883) const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 884) unsigned int size = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 885)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 886) if (!buffer) {
431547b3c4533 (Christoph Hellwig 2009-11-13 09:52:56 +0000 887) for_each_xattr_handler(handlers, handler) {
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 888) if (!handler->name ||
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 889) (handler->list && !handler->list(dentry)))
c4803c497fbdb (Andreas Gruenbacher 2015-12-02 14:44:41 +0100 890) continue;
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 891) size += strlen(handler->name) + 1;
431547b3c4533 (Christoph Hellwig 2009-11-13 09:52:56 +0000 892) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 893) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 894) char *buf = buffer;
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 895) size_t len;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 896)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 897) for_each_xattr_handler(handlers, handler) {
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 898) if (!handler->name ||
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 899) (handler->list && !handler->list(dentry)))
c4803c497fbdb (Andreas Gruenbacher 2015-12-02 14:44:41 +0100 900) continue;
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 901) len = strlen(handler->name);
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 902) if (len + 1 > buffer_size)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 903) return -ERANGE;
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 904) memcpy(buf, handler->name, len + 1);
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 905) buf += len + 1;
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 906) buffer_size -= len + 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 907) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 908) size = buf - buffer;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 909) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 910) return size;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 911) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 912) EXPORT_SYMBOL(generic_listxattr);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 913)
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 914) /**
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 915) * xattr_full_name - Compute full attribute name from suffix
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 916) *
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 917) * @handler: handler of the xattr_handler operation
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 918) * @name: name passed to the xattr_handler operation
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 919) *
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 920) * The get and set xattr handler operations are called with the remainder of
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 921) * the attribute name after skipping the handler's prefix: for example, "foo"
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 922) * is passed to the get operation of a handler with prefix "user." to get
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 923) * attribute "user.foo". The full name is still "there" in the name though.
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 924) *
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 925) * Note: the list xattr handler operation when called from the vfs is passed a
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 926) * NULL name; some file systems use this operation internally, with varying
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 927) * semantics.
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 928) */
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 929) const char *xattr_full_name(const struct xattr_handler *handler,
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 930) const char *name)
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 931) {
98e9cb5711c68 (Andreas Gruenbacher 2015-12-02 14:44:36 +0100 932) size_t prefix_len = strlen(xattr_prefix(handler));
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 933)
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 934) return name - prefix_len;
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 935) }
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 936) EXPORT_SYMBOL(xattr_full_name);
e409de992e3ea (Andreas Gruenbacher 2015-10-04 19:18:52 +0200 937)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 938) /*
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 939) * Allocate new xattr and copy in the value; but leave the name to callers.
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 940) */
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 941) struct simple_xattr *simple_xattr_alloc(const void *value, size_t size)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 942) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 943) struct simple_xattr *new_xattr;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 944) size_t len;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 945)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 946) /* wrap around? */
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 947) len = sizeof(*new_xattr) + size;
4e66d445d0421 (Hugh Dickins 2014-07-23 14:00:17 -0700 948) if (len < sizeof(*new_xattr))
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 949) return NULL;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 950)
fdc85222d58eb (Daniel Xu 2020-03-12 13:03:14 -0700 951) new_xattr = kvmalloc(len, GFP_KERNEL);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 952) if (!new_xattr)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 953) return NULL;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 954)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 955) new_xattr->size = size;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 956) memcpy(new_xattr->value, value, size);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 957) return new_xattr;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 958) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 959)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 960) /*
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 961) * xattr GET operation for in-memory/pseudo filesystems
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 962) */
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 963) int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 964) void *buffer, size_t size)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 965) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 966) struct simple_xattr *xattr;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 967) int ret = -ENODATA;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 968)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 969) spin_lock(&xattrs->lock);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 970) list_for_each_entry(xattr, &xattrs->head, list) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 971) if (strcmp(name, xattr->name))
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 972) continue;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 973)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 974) ret = xattr->size;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 975) if (buffer) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 976) if (size < xattr->size)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 977) ret = -ERANGE;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 978) else
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 979) memcpy(buffer, xattr->value, xattr->size);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 980) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 981) break;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 982) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 983) spin_unlock(&xattrs->lock);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 984) return ret;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 985) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 986)
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 987) /**
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 988) * simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 989) * @xattrs: target simple_xattr list
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 990) * @name: name of the extended attribute
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 991) * @value: value of the xattr. If %NULL, will remove the attribute.
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 992) * @size: size of the new xattr
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 993) * @flags: %XATTR_{CREATE|REPLACE}
a46a22955bae1 (Daniel Xu 2020-03-12 13:03:15 -0700 994) * @removed_size: returns size of the removed xattr, -1 if none removed
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 995) *
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 996) * %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 997) * with -EEXIST. If %XATTR_REPLACE is set, the xattr should exist;
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 998) * otherwise, fails with -ENODATA.
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 999) *
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 1000) * Returns 0 on success, -errno on failure.
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 1001) */
aa7c5241c380a (Andreas Gruenbacher 2015-12-02 14:44:38 +0100 1002) int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
a46a22955bae1 (Daniel Xu 2020-03-12 13:03:15 -0700 1003) const void *value, size_t size, int flags,
a46a22955bae1 (Daniel Xu 2020-03-12 13:03:15 -0700 1004) ssize_t *removed_size)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1005) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1006) struct simple_xattr *xattr;
43385846968b0 (David Rientjes 2012-10-17 20:41:15 -0700 1007) struct simple_xattr *new_xattr = NULL;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1008) int err = 0;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1009)
772b314066924 (Daniel Xu 2020-04-08 23:27:29 -0700 1010) if (removed_size)
772b314066924 (Daniel Xu 2020-04-08 23:27:29 -0700 1011) *removed_size = -1;
772b314066924 (Daniel Xu 2020-04-08 23:27:29 -0700 1012)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1013) /* value == NULL means remove */
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1014) if (value) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1015) new_xattr = simple_xattr_alloc(value, size);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1016) if (!new_xattr)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1017) return -ENOMEM;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1018)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1019) new_xattr->name = kstrdup(name, GFP_KERNEL);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1020) if (!new_xattr->name) {
fdc85222d58eb (Daniel Xu 2020-03-12 13:03:14 -0700 1021) kvfree(new_xattr);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1022) return -ENOMEM;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1023) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1024) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1025)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1026) spin_lock(&xattrs->lock);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1027) list_for_each_entry(xattr, &xattrs->head, list) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1028) if (!strcmp(name, xattr->name)) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1029) if (flags & XATTR_CREATE) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1030) xattr = new_xattr;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1031) err = -EEXIST;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1032) } else if (new_xattr) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1033) list_replace(&xattr->list, &new_xattr->list);
a46a22955bae1 (Daniel Xu 2020-03-12 13:03:15 -0700 1034) if (removed_size)
a46a22955bae1 (Daniel Xu 2020-03-12 13:03:15 -0700 1035) *removed_size = xattr->size;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1036) } else {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1037) list_del(&xattr->list);
a46a22955bae1 (Daniel Xu 2020-03-12 13:03:15 -0700 1038) if (removed_size)
a46a22955bae1 (Daniel Xu 2020-03-12 13:03:15 -0700 1039) *removed_size = xattr->size;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1040) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1041) goto out;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1042) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1043) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1044) if (flags & XATTR_REPLACE) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1045) xattr = new_xattr;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1046) err = -ENODATA;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1047) } else {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1048) list_add(&new_xattr->list, &xattrs->head);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1049) xattr = NULL;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1050) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1051) out:
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1052) spin_unlock(&xattrs->lock);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1053) if (xattr) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1054) kfree(xattr->name);
fdc85222d58eb (Daniel Xu 2020-03-12 13:03:14 -0700 1055) kvfree(xattr);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1056) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1057) return err;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1058)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1059) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1060)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1061) static bool xattr_is_trusted(const char *name)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1062) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1063) return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1064) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1065)
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1066) static int xattr_list_one(char **buffer, ssize_t *remaining_size,
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1067) const char *name)
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1068) {
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1069) size_t len = strlen(name) + 1;
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1070) if (*buffer) {
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1071) if (*remaining_size < len)
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1072) return -ERANGE;
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1073) memcpy(*buffer, name, len);
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1074) *buffer += len;
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1075) }
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1076) *remaining_size -= len;
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1077) return 0;
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1078) }
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1079)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1080) /*
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1081) * xattr LIST operation for in-memory/pseudo filesystems
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1082) */
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1083) ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1084) char *buffer, size_t size)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1085) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1086) bool trusted = capable(CAP_SYS_ADMIN);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1087) struct simple_xattr *xattr;
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1088) ssize_t remaining_size = size;
0e9a7da51b028 (Mateusz Guzik 2016-02-04 02:56:30 +0100 1089) int err = 0;
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1090)
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1091) #ifdef CONFIG_FS_POSIX_ACL
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1092) if (IS_POSIXACL(inode)) {
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1093) if (inode->i_acl) {
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1094) err = xattr_list_one(&buffer, &remaining_size,
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1095) XATTR_NAME_POSIX_ACL_ACCESS);
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1096) if (err)
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1097) return err;
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1098) }
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1099) if (inode->i_default_acl) {
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1100) err = xattr_list_one(&buffer, &remaining_size,
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1101) XATTR_NAME_POSIX_ACL_DEFAULT);
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1102) if (err)
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1103) return err;
ffc4c92227db5 (Andreas Gruenbacher 2018-09-18 00:36:36 -0400 1104) }
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1105) }
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1106) #endif
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1107)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1108) spin_lock(&xattrs->lock);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1109) list_for_each_entry(xattr, &xattrs->head, list) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1110) /* skip "trusted." attributes for unprivileged callers */
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1111) if (!trusted && xattr_is_trusted(xattr->name))
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1112) continue;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1113)
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1114) err = xattr_list_one(&buffer, &remaining_size, xattr->name);
786534b92f3ce (Andreas Gruenbacher 2015-12-02 14:44:39 +0100 1115) if (err)
0e9a7da51b028 (Mateusz Guzik 2016-02-04 02:56:30 +0100 1116) break;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1117) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1118) spin_unlock(&xattrs->lock);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1119)
0e9a7da51b028 (Mateusz Guzik 2016-02-04 02:56:30 +0100 1120) return err ? err : size - remaining_size;
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1121) }
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1122)
4895768b6aab5 (Aristeu Rozanski 2012-09-11 16:28:11 -0400 1123) /*
4895768b6aab5 (Aristeu Rozanski 2012-09-11 16:28:11 -0400 1124) * Adds an extended attribute to the list
4895768b6aab5 (Aristeu Rozanski 2012-09-11 16:28:11 -0400 1125) */
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1126) void simple_xattr_list_add(struct simple_xattrs *xattrs,
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1127) struct simple_xattr *new_xattr)
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1128) {
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1129) spin_lock(&xattrs->lock);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1130) list_add(&new_xattr->list, &xattrs->head);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1131) spin_unlock(&xattrs->lock);
38f38657444d1 (Aristeu Rozanski 2012-08-23 16:53:28 -0400 1132) }