Skip to content

Commit

Permalink
tmpfs: listxattr should include POSIX ACL xattrs
Browse files Browse the repository at this point in the history
When a file on tmpfs has an ACL or a Default ACL, listxattr should include the
corresponding xattr name.

Signed-off-by: Andreas Gruenbacher <[email protected]>
Reviewed-by: James Morris <[email protected]>
Cc: Hugh Dickins <[email protected]>
Cc: [email protected]
Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
Andreas Gruenbacher authored and Al Viro committed Dec 7, 2015
1 parent aa7c524 commit 786534b
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 19 deletions.
2 changes: 1 addition & 1 deletion fs/kernfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
53 changes: 37 additions & 16 deletions fs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/*
Expand Down
3 changes: 2 additions & 1 deletion include/linux/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion mm/shmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down

0 comments on commit 786534b

Please sign in to comment.