[v2,14/11] fuse: allow splicing to trusted mounts only

Message ID 7j2y6xumiqxpkpqlakrvoribzin73y2p2rokgryyahegjvwo3h@tarta.nabijaczleweli.xyz
State New
Headers
Series Avoid unprivileged splice(file->)/(->socket) pipe exclusion |

Commit Message

Ahelenia Ziemiańska Dec. 24, 2023, 5:01 a.m. UTC
  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(-)
  

Patch

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,