scoutfs: unpriv listxattr_hidden only shows .hide.

Our hidden attributes are hidden so that they don't leak out of
the system when archiving tools transfer xattrs from listxattr along
with the file.  They're not intended to be secret, in fact users want to
see their contents like they want to see other fs metadata that they
can't update which describes the system.

Make our listxattr ioctl only return hidden xattrs and allow anyone to
see the results if they can read the file.   Rename it to more
accurately describe its intended use.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2019-06-28 10:06:25 -07:00
committed by Zach Brown
parent 663ce53109
commit d8bc962fc5
4 changed files with 30 additions and 30 deletions

View File

@@ -693,27 +693,26 @@ out:
return ret;
}
static long scoutfs_ioc_listxattr_raw(struct file *file, unsigned long arg)
/*
* This lists .hide. attributes on the inode. It doesn't include normal
* xattrs that are visible to listxattr because we don't perform as
* rigorous security access checks as normal vfs listxattr does.
*/
static long scoutfs_ioc_listxattr_hidden(struct file *file, unsigned long arg)
{
struct inode *inode = file->f_inode;
struct scoutfs_ioctl_listxattr_raw __user *ulxr = (void __user *)arg;
struct scoutfs_ioctl_listxattr_raw lxr;
struct scoutfs_ioctl_listxattr_hidden __user *ulxr = (void __user *)arg;
struct scoutfs_ioctl_listxattr_hidden lxh;
struct page *page = NULL;
unsigned int bytes;
int total = 0;
int ret;
if (!(file->f_mode & FMODE_READ)) {
ret = -EBADF;
ret = inode_permission(inode, MAY_READ);
if (ret < 0)
goto out;
}
if (!capable(CAP_SYS_ADMIN)) {
ret = -EBADF;
goto out;
}
if (copy_from_user(&lxr, ulxr, sizeof(lxr))) {
if (copy_from_user(&lxh, ulxr, sizeof(lxh))) {
ret = -EFAULT;
goto out;
}
@@ -724,22 +723,22 @@ static long scoutfs_ioc_listxattr_raw(struct file *file, unsigned long arg)
goto out;
}
while (lxr.buf_bytes) {
bytes = min_t(int, lxr.buf_bytes, PAGE_SIZE);
while (lxh.buf_bytes) {
bytes = min_t(int, lxh.buf_bytes, PAGE_SIZE);
ret = scoutfs_list_xattrs(inode, page_address(page), bytes,
&lxr.hash_pos, &lxr.id_pos,
&lxh.hash_pos, &lxh.id_pos,
false, true);
if (ret <= 0)
break;
if (copy_to_user((void __user *)lxr.buf_ptr,
if (copy_to_user((void __user *)lxh.buf_ptr,
page_address(page), ret)) {
ret = -EFAULT;
break;
}
lxr.buf_ptr += ret;
lxr.buf_bytes -= ret;
lxh.buf_ptr += ret;
lxh.buf_bytes -= ret;
total += ret;
ret = 0;
}
@@ -748,8 +747,8 @@ out:
if (page)
__free_page(page);
if (ret == 0 && (__put_user(lxr.hash_pos, &ulxr->hash_pos) ||
__put_user(lxr.id_pos, &ulxr->id_pos)))
if (ret == 0 && (__put_user(lxh.hash_pos, &ulxr->hash_pos) ||
__put_user(lxh.id_pos, &ulxr->id_pos)))
ret = -EFAULT;
return ret ?: total;
@@ -868,8 +867,8 @@ long scoutfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return scoutfs_ioc_data_waiting(file, arg);
case SCOUTFS_IOC_SETATTR_MORE:
return scoutfs_ioc_setattr_more(file, arg);
case SCOUTFS_IOC_LISTXATTR_RAW:
return scoutfs_ioc_listxattr_raw(file, arg);
case SCOUTFS_IOC_LISTXATTR_HIDDEN:
return scoutfs_ioc_listxattr_hidden(file, arg);
case SCOUTFS_IOC_FIND_XATTRS:
return scoutfs_ioc_find_xattrs(file, arg);
}

View File

@@ -306,15 +306,15 @@ struct scoutfs_ioctl_setattr_more {
#define SCOUTFS_IOC_SETATTR_MORE _IOW(SCOUTFS_IOCTL_MAGIC, 8, \
struct scoutfs_ioctl_setattr_more)
struct scoutfs_ioctl_listxattr_raw {
struct scoutfs_ioctl_listxattr_hidden {
__u64 id_pos;
__u64 buf_ptr;
__u32 buf_bytes;
__u32 hash_pos;
};
#define SCOUTFS_IOC_LISTXATTR_RAW _IOR(SCOUTFS_IOCTL_MAGIC, 9, \
struct scoutfs_ioctl_listxattr_raw)
#define SCOUTFS_IOC_LISTXATTR_HIDDEN _IOR(SCOUTFS_IOCTL_MAGIC, 9, \
struct scoutfs_ioctl_listxattr_hidden)
/*
* Return the inode numbers of inodes which might contain the given

View File

@@ -596,7 +596,7 @@ int scoutfs_removexattr(struct dentry *dentry, const char *name)
ssize_t scoutfs_list_xattrs(struct inode *inode, char *buffer,
size_t size, __u32 *hash_pos, __u64 *id_pos,
bool e_range, bool hidden)
bool e_range, bool show_hidden)
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
struct super_block *sb = inode->i_sb;
@@ -607,6 +607,7 @@ ssize_t scoutfs_list_xattrs(struct inode *inode, char *buffer,
unsigned int bytes;
ssize_t total = 0;
u32 name_hash = 0;
bool is_hidden;
u64 id = 0;
int ret;
@@ -638,10 +639,10 @@ ssize_t scoutfs_list_xattrs(struct inode *inode, char *buffer,
break;
}
if (hidden ||
parse_tags(xat->name, xat->name_len, &tgs) != 0 ||
!tgs.hide) {
is_hidden = parse_tags(xat->name, xat->name_len, &tgs) == 0 &&
tgs.hide;
if (show_hidden == is_hidden) {
if (size) {
if ((total + xat->name_len + 1) > size) {
if (e_range)

View File

@@ -9,7 +9,7 @@ int scoutfs_removexattr(struct dentry *dentry, const char *name);
ssize_t scoutfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
ssize_t scoutfs_list_xattrs(struct inode *inode, char *buffer,
size_t size, __u32 *hash_pos, __u64 *id_pos,
bool e_range, bool hidden);
bool e_range, bool show_hidden);
int scoutfs_xattr_drop(struct super_block *sb, u64 ino,
struct scoutfs_lock *lock);