|
8 | 8 | #include <linux/uio.h>
|
9 | 9 | #include <linux/compat.h>
|
10 | 10 | #include <linux/fileattr.h>
|
| 11 | +#include <linux/fsverity.h> |
11 | 12 |
|
12 | 13 | static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args,
|
13 | 14 | struct fuse_ioctl_out *outarg)
|
@@ -117,6 +118,53 @@ static int fuse_copy_ioctl_iovec(struct fuse_conn *fc, struct iovec *dst,
|
117 | 118 | return 0;
|
118 | 119 | }
|
119 | 120 |
|
| 121 | +/* For fs-verity, determine iov lengths from input */ |
| 122 | +static int fuse_setup_measure_verity(unsigned long arg, struct iovec *iov) |
| 123 | +{ |
| 124 | + __u16 digest_size; |
| 125 | + struct fsverity_digest __user *uarg = (void __user *)arg; |
| 126 | + |
| 127 | + if (copy_from_user(&digest_size, &uarg->digest_size, sizeof(digest_size))) |
| 128 | + return -EFAULT; |
| 129 | + |
| 130 | + if (digest_size > SIZE_MAX - sizeof(struct fsverity_digest)) |
| 131 | + return -EINVAL; |
| 132 | + |
| 133 | + iov->iov_len = sizeof(struct fsverity_digest) + digest_size; |
| 134 | + |
| 135 | + return 0; |
| 136 | +} |
| 137 | + |
| 138 | +static int fuse_setup_enable_verity(unsigned long arg, struct iovec *iov, |
| 139 | + unsigned int *in_iovs) |
| 140 | +{ |
| 141 | + struct fsverity_enable_arg enable; |
| 142 | + struct fsverity_enable_arg __user *uarg = (void __user *)arg; |
| 143 | + const __u32 max_buffer_len = FUSE_MAX_MAX_PAGES * PAGE_SIZE; |
| 144 | + |
| 145 | + if (copy_from_user(&enable, uarg, sizeof(enable))) |
| 146 | + return -EFAULT; |
| 147 | + |
| 148 | + if (enable.salt_size > max_buffer_len || enable.sig_size > max_buffer_len) |
| 149 | + return -ENOMEM; |
| 150 | + |
| 151 | + if (enable.salt_size > 0) { |
| 152 | + iov++; |
| 153 | + (*in_iovs)++; |
| 154 | + |
| 155 | + iov->iov_base = u64_to_user_ptr(enable.salt_ptr); |
| 156 | + iov->iov_len = enable.salt_size; |
| 157 | + } |
| 158 | + |
| 159 | + if (enable.sig_size > 0) { |
| 160 | + iov++; |
| 161 | + (*in_iovs)++; |
| 162 | + |
| 163 | + iov->iov_base = u64_to_user_ptr(enable.sig_ptr); |
| 164 | + iov->iov_len = enable.sig_size; |
| 165 | + } |
| 166 | + return 0; |
| 167 | +} |
120 | 168 |
|
121 | 169 | /*
|
122 | 170 | * 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,
|
227 | 275 | out_iov = iov;
|
228 | 276 | out_iovs = 1;
|
229 | 277 | }
|
| 278 | + |
| 279 | + err = 0; |
| 280 | + switch (cmd) { |
| 281 | + case FS_IOC_MEASURE_VERITY: |
| 282 | + err = fuse_setup_measure_verity(arg, iov); |
| 283 | + break; |
| 284 | + case FS_IOC_ENABLE_VERITY: |
| 285 | + err = fuse_setup_enable_verity(arg, iov, &in_iovs); |
| 286 | + break; |
| 287 | + } |
| 288 | + if (err) |
| 289 | + goto out; |
230 | 290 | }
|
231 | 291 |
|
232 | 292 | retry:
|
|
0 commit comments