Skip to content

Commit 9fe2a03

Browse files
richardfungMiklos Szeredi
authored andcommitted
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>
1 parent 413e8f0 commit 9fe2a03

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

fs/fuse/ioctl.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/uio.h>
99
#include <linux/compat.h>
1010
#include <linux/fileattr.h>
11+
#include <linux/fsverity.h>
1112

1213
static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args,
1314
struct fuse_ioctl_out *outarg)
@@ -117,6 +118,53 @@ static int fuse_copy_ioctl_iovec(struct fuse_conn *fc, struct iovec *dst,
117118
return 0;
118119
}
119120

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+
}
120168

121169
/*
122170
* 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,
227275
out_iov = iov;
228276
out_iovs = 1;
229277
}
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;
230290
}
231291

232292
retry:

0 commit comments

Comments
 (0)