tmpfs: listxattr should include POSIX ACL xattrs
When a file on tmpfs has an ACL or a Default ACL, listxattr should include the corresponding xattr name. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: James Morris <james.l.morris@oracle.com> Cc: Hugh Dickins <hughd@google.com> Cc: linux-mm@kvack.org Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
aa7c5241c3
commit
786534b92f
@ -230,7 +230,7 @@ ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
return simple_xattr_list(&attrs->xattrs, buf, size);
|
||||
return simple_xattr_list(d_inode(dentry), &attrs->xattrs, buf, size);
|
||||
}
|
||||
|
||||
static inline void set_default_inode_attr(struct inode *inode, umode_t mode)
|
||||
|
53
fs/xattr.c
53
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -104,7 +104,8 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
|
||||
void *buffer, size_t size);
|
||||
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
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);
|
||||
void simple_xattr_list_add(struct simple_xattrs *xattrs,
|
||||
struct simple_xattr *new_xattr);
|
||||
|
||||
|
@ -2606,7 +2606,7 @@ static const struct xattr_handler *shmem_xattr_handlers[] = {
|
||||
static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
{
|
||||
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
|
||||
return simple_xattr_list(&info->xattrs, buffer, size);
|
||||
return simple_xattr_list(d_inode(dentry), &info->xattrs, buffer, size);
|
||||
}
|
||||
#endif /* CONFIG_TMPFS_XATTR */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user