diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2024-05-02 09:16:53 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2024-05-02 09:16:53 +1000 |
commit | bbca37a42780b721f42edfa3600576ddb95ec58a (patch) | |
tree | 6b0603ecfef43b1984cbc5f09cb9ef25c3dc9ebb | |
parent | ae5c66c51b2f179c399c042d887d8524fe437d9f (diff) | |
parent | fa7e19337908f00fbbe944b85bc27f1c7a7c326c (diff) | |
download | linux-next-bbca37a42780b721f42edfa3600576ddb95ec58a.tar.gz |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git
Notice: this object is not reachable from any branch.
Notice: this object is not reachable from any branch.
-rw-r--r-- | fs/fuse/file.c | 10 | ||||
-rw-r--r-- | fs/fuse/ioctl.c | 60 | ||||
-rw-r--r-- | fs/fuse/passthrough.c | 2 |
3 files changed, 64 insertions, 8 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index b57ce41576407b..f39456c65ed7f7 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -935,14 +935,10 @@ static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args, } for (i = 0; i < ap->num_pages; i++) { - struct page *page = ap->pages[i]; + struct folio *folio = page_folio(ap->pages[i]); - if (!err) - SetPageUptodate(page); - else - SetPageError(page); - unlock_page(page); - put_page(page); + folio_end_read(folio, !err); + folio_put(folio); } if (ia->ff) fuse_file_put(ia->ff, false); diff --git a/fs/fuse/ioctl.c b/fs/fuse/ioctl.c index 726640fa439e04..572ce8a82ceb9c 100644 --- a/fs/fuse/ioctl.c +++ b/fs/fuse/ioctl.c @@ -8,6 +8,7 @@ #include <linux/uio.h> #include <linux/compat.h> #include <linux/fileattr.h> +#include <linux/fsverity.h> static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args, struct fuse_ioctl_out *outarg) @@ -117,6 +118,53 @@ static int fuse_copy_ioctl_iovec(struct fuse_conn *fc, struct iovec *dst, return 0; } +/* For fs-verity, determine iov lengths from input */ +static int fuse_setup_measure_verity(unsigned long arg, struct iovec *iov) +{ + __u16 digest_size; + struct fsverity_digest __user *uarg = (void __user *)arg; + + if (copy_from_user(&digest_size, &uarg->digest_size, sizeof(digest_size))) + return -EFAULT; + + if (digest_size > SIZE_MAX - sizeof(struct fsverity_digest)) + return -EINVAL; + + iov->iov_len = sizeof(struct fsverity_digest) + digest_size; + + return 0; +} + +static int fuse_setup_enable_verity(unsigned long arg, struct iovec *iov, + unsigned int *in_iovs) +{ + struct fsverity_enable_arg enable; + struct fsverity_enable_arg __user *uarg = (void __user *)arg; + const __u32 max_buffer_len = FUSE_MAX_MAX_PAGES * PAGE_SIZE; + + if (copy_from_user(&enable, uarg, sizeof(enable))) + return -EFAULT; + + if (enable.salt_size > max_buffer_len || enable.sig_size > max_buffer_len) + return -ENOMEM; + + if (enable.salt_size > 0) { + iov++; + (*in_iovs)++; + + iov->iov_base = u64_to_user_ptr(enable.salt_ptr); + iov->iov_len = enable.salt_size; + } + + if (enable.sig_size > 0) { + iov++; + (*in_iovs)++; + + iov->iov_base = u64_to_user_ptr(enable.sig_ptr); + iov->iov_len = enable.sig_size; + } + return 0; +} /* * For ioctls, there is no generic way to determine how much memory @@ -227,6 +275,18 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, out_iov = iov; out_iovs = 1; } + + err = 0; + switch (cmd) { + case FS_IOC_MEASURE_VERITY: + err = fuse_setup_measure_verity(arg, iov); + break; + case FS_IOC_ENABLE_VERITY: + err = fuse_setup_enable_verity(arg, iov, &in_iovs); + break; + } + if (err) + goto out; } retry: diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index 1567f0323858bf..9666d13884ce59 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -225,7 +225,7 @@ int fuse_backing_open(struct fuse_conn *fc, struct fuse_backing_map *map) goto out; res = -EINVAL; - if (map->flags) + if (map->flags || map->padding) goto out; file = fget(map->fd); |