forked from Minki/linux
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)
|
if (!attrs)
|
||||||
return -ENOMEM;
|
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)
|
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);
|
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
|
* xattr LIST operation for in-memory/pseudo filesystems
|
||||||
*/
|
*/
|
||||||
ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer,
|
ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
|
||||||
size_t size)
|
char *buffer, size_t size)
|
||||||
{
|
{
|
||||||
bool trusted = capable(CAP_SYS_ADMIN);
|
bool trusted = capable(CAP_SYS_ADMIN);
|
||||||
struct simple_xattr *xattr;
|
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);
|
spin_lock(&xattrs->lock);
|
||||||
list_for_each_entry(xattr, &xattrs->head, list) {
|
list_for_each_entry(xattr, &xattrs->head, list) {
|
||||||
size_t len;
|
|
||||||
|
|
||||||
/* skip "trusted." attributes for unprivileged callers */
|
/* skip "trusted." attributes for unprivileged callers */
|
||||||
if (!trusted && xattr_is_trusted(xattr->name))
|
if (!trusted && xattr_is_trusted(xattr->name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
len = strlen(xattr->name) + 1;
|
err = xattr_list_one(&buffer, &remaining_size, xattr->name);
|
||||||
used += len;
|
if (err)
|
||||||
if (buffer) {
|
return err;
|
||||||
if (size < used) {
|
|
||||||
used = -ERANGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
memcpy(buffer, xattr->name, len);
|
|
||||||
buffer += len;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
spin_unlock(&xattrs->lock);
|
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);
|
void *buffer, size_t size);
|
||||||
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
||||||
const void *value, size_t size, int flags);
|
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,
|
void simple_xattr_list_add(struct simple_xattrs *xattrs,
|
||||||
struct simple_xattr *new_xattr);
|
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)
|
static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||||
{
|
{
|
||||||
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
|
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 */
|
#endif /* CONFIG_TMPFS_XATTR */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user