diff options
Diffstat (limited to 'fs/xattr.c')
-rw-r--r-- | fs/xattr.c | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/fs/xattr.c b/fs/xattr.c index 4ef8b378dc90..c3af6c9670cb 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -921,38 +921,59 @@ 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; +} + /* * xattr LIST operation for in-memory/pseudo filesystems */ -ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer, - size_t size) +ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, + char *buffer, size_t size) { bool trusted = capable(CAP_SYS_ADMIN); struct simple_xattr *xattr; - size_t used = 0; + ssize_t remaining_size = size; + int err; + +#ifdef CONFIG_FS_POSIX_ACL + 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 spin_lock(&xattrs->lock); list_for_each_entry(xattr, &xattrs->head, list) { - size_t len; - /* skip "trusted." attributes for unprivileged callers */ if (!trusted && xattr_is_trusted(xattr->name)) continue; - len = strlen(xattr->name) + 1; - used += len; - if (buffer) { - if (size < used) { - used = -ERANGE; - break; - } - memcpy(buffer, xattr->name, len); - buffer += len; - } + err = xattr_list_one(&buffer, &remaining_size, xattr->name); + if (err) + return err; } spin_unlock(&xattrs->lock); - return used; + return size - remaining_size; } /* |