fuse: Add initial support for fs-verity
This adds support for the FS_IOC_ENABLE_VERITY and FS_IOC_MEASURE_VERITY ioctls. The FS_IOC_READ_VERITY_METADATA is missing but from the documentation, "This is a fairly specialized use case, and most fs-verity users won’t need this ioctl." Signed-off-by: Richard Fung <richardfung@google.com> Acked-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
413e8f014c
commit
9fe2a036a2
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue