From 213eef54672ce225122dc90ef063dc4e878a074a Mon Sep 17 00:00:00 2001 From: Benjamin Coddington Date: Thu, 27 Jun 2024 08:14:01 -0400 Subject: [PATCH] xattr: simplify listxattr helpers JIRA: https://issues.redhat.com/browse/RHEL-34875 Conflicts: context differences in posix_acl.h due to various VFS updates not yet in RHEL. commit f2620f166e2a4db08f016b7b30b904ab28c265e4 Author: Christian Brauner Date: Wed Feb 1 14:14:52 2023 +0100 xattr: simplify listxattr helpers The generic_listxattr() and simple_xattr_list() helpers list xattrs and contain duplicated code. Add two helpers that both generic_listxattr() and simple_xattr_list() can use. Reviewed-by: Christoph Hellwig Signed-off-by: Christian Brauner (Microsoft) Signed-off-by: Benjamin Coddington --- fs/posix_acl.c | 25 ++++++++++++ fs/xattr.c | 85 ++++++++++++++------------------------- include/linux/posix_acl.h | 7 ++++ include/linux/xattr.h | 1 + 4 files changed, 64 insertions(+), 54 deletions(-) diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 67c307ca8e12..b4b03ffff527 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -958,6 +958,31 @@ posix_acl_xattr_set(const struct xattr_handler *handler, return ret; } +int posix_acl_listxattr(struct inode *inode, char **buffer, + ssize_t *remaining_size) +{ + int err; + + if (!IS_POSIXACL(inode)) + return 0; + + if (inode->i_acl) { + err = xattr_list_one(buffer, remaining_size, + XATTR_NAME_POSIX_ACL_ACCESS); + if (err) + return err; + } + + if (inode->i_default_acl) { + err = xattr_list_one(buffer, remaining_size, + XATTR_NAME_POSIX_ACL_DEFAULT); + if (err) + return err; + } + + return 0; +} + static bool posix_acl_xattr_list(struct dentry *dentry) { diff --git a/fs/xattr.c b/fs/xattr.c index 09bd1bf59bff..516f48e2cc8f 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -927,6 +927,21 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) return error; } +int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name) +{ + size_t len; + + len = strlen(name) + 1; + if (*buffer) { + if (*remaining_size < len) + return -ERANGE; + memcpy(*buffer, name, len); + *buffer += len; + } + *remaining_size -= len; + return 0; +} + /* * Combine the results of the list() operation from every xattr_handler in the * list. @@ -935,33 +950,22 @@ ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) { const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr; - unsigned int size = 0; + ssize_t remaining_size = buffer_size; + int err = 0; - if (!buffer) { - for_each_xattr_handler(handlers, handler) { - if (!handler->name || - (handler->list && !handler->list(dentry))) - continue; - size += strlen(handler->name) + 1; - } - } else { - char *buf = buffer; - size_t len; + err = posix_acl_listxattr(d_inode(dentry), &buffer, &remaining_size); + if (err) + return err; - for_each_xattr_handler(handlers, handler) { - if (!handler->name || - (handler->list && !handler->list(dentry))) - continue; - len = strlen(handler->name); - if (len + 1 > buffer_size) - return -ERANGE; - memcpy(buf, handler->name, len + 1); - buf += len + 1; - buffer_size -= len + 1; - } - size = buf - buffer; + for_each_xattr_handler(handlers, handler) { + if (!handler->name || (handler->list && !handler->list(dentry))) + continue; + err = xattr_list_one(&buffer, &remaining_size, handler->name); + if (err) + return err; } - return size; + + return err ? err : buffer_size - remaining_size; } EXPORT_SYMBOL(generic_listxattr); @@ -1223,20 +1227,6 @@ static bool xattr_is_trusted(const char *name) return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); } -static int xattr_list_one(char **buffer, ssize_t *remaining_size, - const char *name) -{ - size_t len = strlen(name) + 1; - if (*buffer) { - if (*remaining_size < len) - return -ERANGE; - memcpy(*buffer, name, len); - *buffer += len; - } - *remaining_size -= len; - return 0; -} - /** * simple_xattr_list - list all xattr objects * @inode: inode from which to get the xattrs @@ -1265,22 +1255,9 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, ssize_t remaining_size = size; int err = 0; -#ifdef CONFIG_FS_POSIX_ACL - if (IS_POSIXACL(inode)) { - if (inode->i_acl) { - err = xattr_list_one(&buffer, &remaining_size, - XATTR_NAME_POSIX_ACL_ACCESS); - if (err) - return err; - } - if (inode->i_default_acl) { - err = xattr_list_one(&buffer, &remaining_size, - XATTR_NAME_POSIX_ACL_DEFAULT); - if (err) - return err; - } - } -#endif + err = posix_acl_listxattr(inode, &buffer, &remaining_size); + if (err) + return err; read_lock(&xattrs->lock); for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) { diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 307094ebb88c..76299cac00ce 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h @@ -97,6 +97,8 @@ static inline void cache_no_acl(struct inode *inode) inode->i_acl = NULL; inode->i_default_acl = NULL; } +int posix_acl_listxattr(struct inode *inode, char **buffer, + ssize_t *remaining_size); #else static inline int posix_acl_chmod(struct user_namespace *mnt_userns, struct inode *inode, umode_t mode) @@ -124,6 +126,11 @@ static inline int posix_acl_create(struct inode *inode, umode_t *mode, static inline void forget_all_cached_acls(struct inode *inode) { } +static inline int posix_acl_listxattr(struct inode *inode, char **buffer, + ssize_t *remaining_size) +{ + return 0; +} #endif /* CONFIG_FS_POSIX_ACL */ struct posix_acl *get_acl(struct inode *inode, int type); diff --git a/include/linux/xattr.h b/include/linux/xattr.h index 2bcea30acba0..57f97dccb3d2 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -103,5 +103,6 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, char *buffer, size_t size); void simple_xattr_add(struct simple_xattrs *xattrs, struct simple_xattr *new_xattr); +int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name); #endif /* _LINUX_XATTR_H */