FUSE tends to be installed suid 0: this allows normal users to mount anything, including a program whose write implementation consists of for(;;) sleep(1);, which, if splice were allowed, would sleep forever with the pipe lock held. Normal filesystems can only be mounted by root, and are thus deemed safe. Extend this to when root mounts a FUSE filesystem and to virtiofs, mirroring the splice_read "trusted" logic. Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@xxxxxxxxxxxxxxxxxx> --- fs/fuse/file.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 20bb16ddfcc9..62308af13396 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -3215,6 +3215,21 @@ static long fuse_splice_read(struct file *in, loff_t *ppos, return -EINVAL; } +static ssize_t +fuse_splice_write(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) +{ + struct inode *inode = file_inode(out); + + if (fuse_is_bad(inode)) + return -EIO; + + if (get_fuse_conn(inode)->trusted) + return iter_file_splice_write(pipe, out, ppos, len, flags); + + return -EINVAL; +} + static const struct file_operations fuse_file_operations = { .llseek = fuse_file_llseek, .read_iter = fuse_file_read_iter, @@ -3228,7 +3243,7 @@ static const struct file_operations fuse_file_operations = { .get_unmapped_area = thp_get_unmapped_area, .flock = fuse_file_flock, .splice_read = fuse_splice_read, - .splice_write = iter_file_splice_write, + .splice_write = fuse_splice_write, .unlocked_ioctl = fuse_file_ioctl, .compat_ioctl = fuse_file_compat_ioctl, .poll = fuse_file_poll, -- 2.39.2
Attachment:
signature.asc
Description: PGP signature