Linux-man Archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/11] Avoid unprivileged splice(file->)/(->socket) pipe exclusion
@ 2023-12-21  3:08 Ahelenia Ziemiańska
  2023-12-21  3:09 ` [PATCH v2 12/11 man-pages] splice.2: document 6.8 blocking behaviour Ahelenia Ziemiańska
  0 siblings, 1 reply; 2+ messages in thread
From: Ahelenia Ziemiańska @ 2023-12-21  3:08 UTC (permalink / raw
  Cc: Jens Axboe, Christian Brauner, Alexander Viro, linux-fsdevel,
	Greg Kroah-Hartman, Jiri Slaby, Miklos Szeredi, Vivek Goyal,
	Stefan Hajnoczi, Eric Dumazet, David S. Miller, David Ahern,
	Jakub Kicinski, Paolo Abeni, Wenjia Zhang, Jan Karcher, D. Wythe,
	Tony Lu, Wen Gu, Boris Pismenny, John Fastabend, David Howells,
	Shigeru Yoshida, Peilin Ye, Kuniyuki Iwashima,
	Alexander Mikhalitsyn, Daan De Meyer, linux-kernel, linux-serial,
	virtualization, netdev, linux-s390, Alejandro Colomar, linux-man

[-- Attachment #1: Type: text/plain, Size: 4391 bytes --]

Hi!

As it stands, splice(file -> pipe):
1. locks the pipe,
2. does a read from the file,
3. unlocks the pipe.

When the file resides on a normal filesystem, this isn't an issue
because the filesystem has been defined as trusted by root having
mounted it.

But when the file is actually IPC (FUSE) or is just IPC (sockets)
or is a tty, this means that the pipe lock will be held for an
attacker-controlled length of time, and during that time every
process trying to read from, write to, open, or close the pipe
enters an uninterruptible sleep, and will only exit it if the
splicing process is killed.

This trivially denies service to:
* any hypothetical pipe-based log collexion system
* all nullmailer installations
* me, personally, when I'm pasting stuff into qemu -serial chardev:pipe

A symmetric situation happens for splicing(pipe -> socket):
the pipe is locked for as long as the socket is full.

This follows:
1. https://lore.kernel.org/linux-fsdevel/qk6hjuam54khlaikf2ssom6custxf5is2ekkaequf4hvode3ls@zgf7j5j4ubvw/t/#u
2. a security@ thread rooted in
   <irrrblivicfc7o3lfq7yjm2lrxq35iyya4gyozlohw24gdzyg7@azmluufpdfvu>
3. https://nabijaczleweli.xyz/content/blogn_t/011-linux-splice-exclusion.html
4. https://lore.kernel.org/lkml/cover.1697486714.git.nabijaczleweli@nabijaczleweli.xyz/t/#u  (v1)
   https://lore.kernel.org/lkml/1cover.1697486714.git.nabijaczleweli@nabijaczleweli.xyz/t/#u (resend)
   https://lore.kernel.org/lkml/2cover.1697486714.git.nabijaczleweli@nabijaczleweli.xyz/t/#u (reresend)
5. https://lore.kernel.org/lkml/dtexwpw6zcdx7dkx3xj5gyjp5syxmyretdcbcdtvrnukd4vvuh@tarta.nabijaczleweli.xyz/t/#u
   (relay_file_splice_read removal)

1-7/11 request MSG_DONTWAIT (sockets)/IOCB_NOWAIT (generic) on the read

  8/11 removes splice_read from tty completely

  9/11 removes splice_read from FUSE filesystems
       (except virtiofs which has normal mounting security semantics,
        but is handled via FUSE code)

 10/11 allows splice_read from FUSE filesystems mounted by real root
       (this matches the blessing received by non-FUSE network filesystems)

 11/11 requests MSG_DONTWAIT for splice(pipe -> socket).

 12/11 has the man-pages patch with draft wording.

All but 5/11 (AF_SMC) have been tested and embed shell programs to
repro them. AIUI I'd need an s390 machine for it? It's trivial.

6/11 (AF_KCM) also fixes kcm_splice_read() passing SPLICE_F_*-style
flags to skb_recv_datagram(), which takes MSG_*-style flags. I don't
think they did anything anyway? But.

There are two implementations that definitely sleep all the time
and I didn't touch them:
  tracing_splice_read_pipe
  tracing_buffers_splice_read (dropped in v2, v1 4/11)
the semantics are lost on me, but they're in debugfs/tracefs, so
it doesn't matter if they block so long as they work, and presumably
they do right now.

There is also relay_file_splice_read (dropped in v2, v1 5/11),
which isn't an implementation at all because it's dead code, broken,
and removed in -mm.

The diffs in 1-7,11/11 are unchanged, save for a rebase in 7/11.
8/11 replaces the file type test in v1 10/11.
9/11 and 10/11 are new in v2.

Ahelenia Ziemiańska (11):
  splice: copy_splice_read: do the I/O with IOCB_NOWAIT
  af_unix: unix_stream_splice_read: always request MSG_DONTWAIT
  fuse: fuse_dev_splice_read: use nonblocking I/O
  net/smc: smc_splice_read: always request MSG_DONTWAIT
  kcm: kcm_splice_read: always request MSG_DONTWAIT
  tls/sw: tls_sw_splice_read: always request non-blocking I/O
  net/tcp: tcp_splice_read: always do non-blocking reads
  tty: splice_read: disable
  fuse: file: limit splice_read to virtiofs
  fuse: allow splicing from filesystems mounted by real root
  splice: splice_to_socket: always request MSG_DONTWAIT

 drivers/tty/tty_io.c |  2 --
 fs/fuse/dev.c        | 10 ++++++----
 fs/fuse/file.c       | 17 ++++++++++++++++-
 fs/fuse/fuse_i.h     |  4 ++++
 fs/fuse/inode.c      |  2 ++
 fs/fuse/virtio_fs.c  |  1 +
 fs/splice.c          |  5 ++---
 net/ipv4/tcp.c       | 32 +++-----------------------------
 net/kcm/kcmsock.c    |  2 +-
 net/smc/af_smc.c     |  6 +-----
 net/tls/tls_sw.c     |  5 ++---
 net/unix/af_unix.c   |  5 +----
 12 files changed, 39 insertions(+), 52 deletions(-)

base-commit: 2cf4f94d8e8646803f8fb0facf134b0cd7fb691a
--
2.39.2

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH v2 12/11 man-pages] splice.2: document 6.8 blocking behaviour
  2023-12-21  3:08 [PATCH v2 00/11] Avoid unprivileged splice(file->)/(->socket) pipe exclusion Ahelenia Ziemiańska
@ 2023-12-21  3:09 ` Ahelenia Ziemiańska
  0 siblings, 0 replies; 2+ messages in thread
From: Ahelenia Ziemiańska @ 2023-12-21  3:09 UTC (permalink / raw
  Cc: Jens Axboe, Christian Brauner, Alexander Viro, linux-fsdevel,
	Alejandro Colomar, linux-man, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2402 bytes --]

Hypothetical text that matches v2.

Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
---
 man2/splice.2 | 47 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 43 insertions(+), 4 deletions(-)

diff --git a/man2/splice.2 b/man2/splice.2
index e5d05a05c..d2c7ac8d5 100644
--- a/man2/splice.2
+++ b/man2/splice.2
@@ -139,10 +139,11 @@ .SH ERRORS
 .B EAGAIN
 .B SPLICE_F_NONBLOCK
 was specified in
-.I flags
-or one of the file descriptors had been marked as nonblocking
-.RB ( O_NONBLOCK ) ,
-and the operation would block.
+.IR flags ,
+one of the file descriptors had been marked as nonblocking
+.RB ( O_NONBLOCK )
+and the operation would block,
+or splicing from an untrusted IPC mechanism and no data was available (see HISTORY below).
 .TP
 .B EBADF
 One or both file descriptors are not valid,
@@ -192,6 +193,44 @@ .SH HISTORY
 Since Linux 2.6.31,
 .\" commit 7c77f0b3f9208c339a4b40737bb2cb0f0319bb8d
 both arguments may refer to pipes.
+.P
+Between Linux 4.9 and 6.7,
+.\" commit 8924feff66f35fe22ce77aafe3f21eb8e5cff881
+splicing from a non-pipe to a pipe without
+.B SPLICE_F_NONBLOCK
+would hold the pipe lock and wait for data on the non-pipe.
+This isn't an issue for files, but if the non-pipe is a tty,
+or an IPC mechanism like a socket or a
+.BR fuse (4)
+filesystem, this means that a thread attempting any operation (like
+.BR open (2)/ read (2)/ write (2)/ close (2))
+on the pipe would enter uninterruptible sleep until data appeared,
+which may never happen.
+The same applies to splicing from a pipe to a full socket.
+.P
+Since Linux 6.8,
+.\" commit TBD
+splicing from ttys is disabled
+.RB ( EINVAL ),
+reads done when splicing from sockets happen in non-blocking mode
+(as-if
+.BR MSG_DONTWAIT ,
+returning
+.B EAGAIN
+if no data is available),
+and splicing from
+.BR fuse (4)
+filesystems is only allowed if they were mounted by
+root in the initial user namespace
+(this matches security semantics for normal filesystems).
+If a splice implementation is devised that doesn't need to lock the pipe
+while waiting for data, this may be reversed in a future version.
+Writes when splicing to sockets are also done non-blockingly
+(as-if
+.BR MSG_DONTWAIT ,
+returning
+.B EAGAIN
+if the socket is full).
 .SH NOTES
 The three system calls
 .BR splice (),
-- 
2.39.2

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-12-21  3:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-21  3:08 [PATCH v2 00/11] Avoid unprivileged splice(file->)/(->socket) pipe exclusion Ahelenia Ziemiańska
2023-12-21  3:09 ` [PATCH v2 12/11 man-pages] splice.2: document 6.8 blocking behaviour Ahelenia Ziemiańska

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).