| From cb3ae6d25a5471be62bfe6ac1fccc0e91edeaba0 Mon Sep 17 00:00:00 2001 |
| From: Miklos Szeredi <mszeredi@redhat.com> |
| Date: Sat, 1 Oct 2016 07:32:32 +0200 |
| Subject: fuse: listxattr: verify xattr list |
| |
| From: Miklos Szeredi <mszeredi@redhat.com> |
| |
| commit cb3ae6d25a5471be62bfe6ac1fccc0e91edeaba0 upstream. |
| |
| Make sure userspace filesystem is returning a well formed list of xattr |
| names (zero or more nonzero length, null terminated strings). |
| |
| [Michael Theall: only verify in the nonzero size case] |
| |
| Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/fuse/dir.c | 19 +++++++++++++++++++ |
| 1 file changed, 19 insertions(+) |
| |
| --- a/fs/fuse/dir.c |
| +++ b/fs/fuse/dir.c |
| @@ -1800,6 +1800,23 @@ static ssize_t fuse_getxattr(struct dent |
| return ret; |
| } |
| |
| +static int fuse_verify_xattr_list(char *list, size_t size) |
| +{ |
| + size_t origsize = size; |
| + |
| + while (size) { |
| + size_t thislen = strnlen(list, size); |
| + |
| + if (!thislen || thislen == size) |
| + return -EIO; |
| + |
| + size -= thislen + 1; |
| + list += thislen + 1; |
| + } |
| + |
| + return origsize; |
| +} |
| + |
| static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) |
| { |
| struct inode *inode = d_inode(entry); |
| @@ -1835,6 +1852,8 @@ static ssize_t fuse_listxattr(struct den |
| ret = fuse_simple_request(fc, &args); |
| if (!ret && !size) |
| ret = outarg.size; |
| + if (ret > 0 && size) |
| + ret = fuse_verify_xattr_list(list, ret); |
| if (ret == -ENOSYS) { |
| fc->no_listxattr = 1; |
| ret = -EOPNOTSUPP; |