From e2dfffcab9b8b438086f65e2b78492a2f17f8b20 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 2 Dec 2020 09:42:22 -0800 Subject: [PATCH] scoutfs: search_xattrs name requires srch tag The search_xattrs ioctl is only going to find entries for xattrs with the .srch. tag which create srch entries as they're created and destroyed. Export the xattr tag parsing so that the ioctl can return -EINVAL for xattrs which don't have the scoutfs prefix and the .srch. tag. Signed-off-by: Zach Brown --- kmod/src/ioctl.c | 7 +++++++ kmod/src/xattr.c | 25 +++++++++++-------------- kmod/src/xattr.h | 8 ++++++++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/kmod/src/ioctl.c b/kmod/src/ioctl.c index accff1ee..cfb06462 100644 --- a/kmod/src/ioctl.c +++ b/kmod/src/ioctl.c @@ -767,6 +767,7 @@ static long scoutfs_ioc_search_xattrs(struct file *file, unsigned long arg) struct super_block *sb = file_inode(file)->i_sb; struct scoutfs_ioctl_search_xattrs __user *usx = (void __user *)arg; struct scoutfs_ioctl_search_xattrs sx; + struct scoutfs_xattr_prefix_tags tgs; struct scoutfs_srch_rb_root sroot; struct scoutfs_srch_rb_node *snode; u64 __user *uinos; @@ -814,6 +815,12 @@ static long scoutfs_ioc_search_xattrs(struct file *file, unsigned long arg) goto out; } + if (scoutfs_xattr_parse_tags(name, sx.name_bytes, &tgs) < 0 || + !tgs.srch) { + ret = -EINVAL; + goto out; + } + ret = scoutfs_srch_search_xattrs(sb, &sroot, scoutfs_hash64(name, sx.name_bytes), sx.next_ino, sx.last_ino, &done); diff --git a/kmod/src/xattr.c b/kmod/src/xattr.c index 1b579132..824b549b 100644 --- a/kmod/src/xattr.c +++ b/kmod/src/xattr.c @@ -94,21 +94,17 @@ static int unknown_prefix(const char *name) strncmp(name, SCOUTFS_XATTR_PREFIX, SCOUTFS_XATTR_PREFIX_LEN); } -struct prefix_tags { - unsigned long hide:1, - srch:1; -}; #define HIDE_TAG "hide." #define SRCH_TAG "srch." #define TAG_LEN (sizeof(HIDE_TAG) - 1) -static int parse_tags(const char *name, unsigned int name_len, - struct prefix_tags *tgs) +int scoutfs_xattr_parse_tags(const char *name, unsigned int name_len, + struct scoutfs_xattr_prefix_tags *tgs) { bool found; - memset(tgs, 0, sizeof(struct prefix_tags)); + memset(tgs, 0, sizeof(struct scoutfs_xattr_prefix_tags)); if ((name_len < (SCOUTFS_XATTR_PREFIX_LEN + TAG_LEN + 1)) || strncmp(name, SCOUTFS_XATTR_PREFIX, SCOUTFS_XATTR_PREFIX_LEN)) @@ -490,11 +486,11 @@ static int scoutfs_xattr_set(struct dentry *dentry, const char *name, struct scoutfs_inode_info *si = SCOUTFS_I(inode); struct super_block *sb = inode->i_sb; const u64 ino = scoutfs_ino(inode); + struct scoutfs_xattr_prefix_tags tgs; struct scoutfs_xattr *xat = NULL; struct scoutfs_lock *lck = NULL; size_t name_len = strlen(name); struct scoutfs_key key; - struct prefix_tags tgs; bool undo_srch = false; LIST_HEAD(ind_locks); u8 found_parts; @@ -520,7 +516,7 @@ static int scoutfs_xattr_set(struct dentry *dentry, const char *name, if (unknown_prefix(name)) return -EOPNOTSUPP; - if (parse_tags(name, name_len, &tgs) != 0) + if (scoutfs_xattr_parse_tags(name, name_len, &tgs) != 0) return -EINVAL; if ((tgs.hide || tgs.srch) && !capable(CAP_SYS_ADMIN)) @@ -659,10 +655,10 @@ ssize_t scoutfs_list_xattrs(struct inode *inode, char *buffer, { struct scoutfs_inode_info *si = SCOUTFS_I(inode); struct super_block *sb = inode->i_sb; + struct scoutfs_xattr_prefix_tags tgs; struct scoutfs_xattr *xat = NULL; struct scoutfs_lock *lck = NULL; struct scoutfs_key key; - struct prefix_tags tgs; unsigned int bytes; ssize_t total = 0; u32 name_hash = 0; @@ -698,8 +694,8 @@ ssize_t scoutfs_list_xattrs(struct inode *inode, char *buffer, break; } - is_hidden = parse_tags(xat->name, xat->name_len, &tgs) == 0 && - tgs.hide; + is_hidden = scoutfs_xattr_parse_tags(xat->name, xat->name_len, + &tgs) == 0 && tgs.hide; if (show_hidden == is_hidden) { if (size) { @@ -751,10 +747,10 @@ ssize_t scoutfs_listxattr(struct dentry *dentry, char *buffer, size_t size) int scoutfs_xattr_drop(struct super_block *sb, u64 ino, struct scoutfs_lock *lock) { + struct scoutfs_xattr_prefix_tags tgs; struct scoutfs_xattr *xat = NULL; struct scoutfs_key last; struct scoutfs_key key; - struct prefix_tags tgs; bool release = false; unsigned int bytes; u64 hash; @@ -781,7 +777,8 @@ int scoutfs_xattr_drop(struct super_block *sb, u64 ino, } if (key.skx_part != 0 || - parse_tags(xat->name, xat->name_len, &tgs) != 0) + scoutfs_xattr_parse_tags(xat->name, xat->name_len, + &tgs) != 0) memset(&tgs, 0, sizeof(tgs)); ret = scoutfs_hold_trans(sb, SIC_EXACT(2, 0)); diff --git a/kmod/src/xattr.h b/kmod/src/xattr.h index 8af0026f..39313801 100644 --- a/kmod/src/xattr.h +++ b/kmod/src/xattr.h @@ -14,4 +14,12 @@ ssize_t scoutfs_list_xattrs(struct inode *inode, char *buffer, int scoutfs_xattr_drop(struct super_block *sb, u64 ino, struct scoutfs_lock *lock); +struct scoutfs_xattr_prefix_tags { + unsigned long hide:1, + srch:1; +}; + +int scoutfs_xattr_parse_tags(const char *name, unsigned int name_len, + struct scoutfs_xattr_prefix_tags *tgs); + #endif