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@nabijaczleweli.xyz>
---
fs/fuse/file.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
@@ -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,