[lkml]   [2021]   [Jan]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    SubjectRe: Splicing to/from a tty
    On Sun Jan 17, 2021 at 5:46 AM NZDT, Johannes Berg wrote:
    > On Sat, 2021-01-16 at 20:35 +1300, Oliver Giles wrote:
    > > Commit 36e2c7421f02 (fs: don't allow splice read/write without
    > > explicit ops) broke my userspace application which talks to an SSL VPN
    > > by splice()ing between "openssl s_client" and "pppd". The latter
    > > operates over a pty, and since that commit there is no fallback for
    > > splice()ing between a pipe and a pty, or any tty for that matter.
    > >
    > > The above commit mentions switching them to the iter ops and using
    > > generic_file_splice_read. IIUC, this would require implementing iter
    > > ops also on the line disciplines, which sounds pretty disruptive.
    > >
    > > For my case, I attempted to instead implement splice_write and
    > > splice_read in tty_fops; I managed to get splice_write working calling
    > > ld->ops->write, but splice_read is not so simple because the
    > > tty_ldisc_ops read method expects a userspace buffer. So I cannot see
    > > how to implement this without either (a) using set_fs, or (b)
    > > implementing iter ops on all line disciplines.
    > >
    > > Is splice()ing between a tty and a pipe worth supporting at all? Not a
    > > big deal for my use case at least, but it used to work.
    > Is it even strictly related to the tty?
    > I was just now looking into why my cgit/fcgi/nginx setup no longer
    > works, and the reason is getting -EINVAL from sendfile() when the input
    > is a file and the output is a pipe().
    > So I wrote a simple test program (below) and that errors out on kernel
    > 5.10.4, while it works fine on the 5.9.16 I currently have. Haven't
    > tried reverting anything yet, but now that I haev a test program it
    > should be simple to even bisect.
    > johannes
    > #include <unistd.h>
    > #include <sys/types.h>
    > #include <sys/stat.h>
    > #include <fcntl.h>
    > #include <sys/sendfile.h>
    > #include <stdio.h>
    > #include <assert.h>
    > int main(int argc, char **argv)
    > {
    > int in = open(argv[0], O_RDONLY);
    > int p[2], out;
    > off_t off = 0;
    > int err;
    > assert(in >= 0);
    > assert(pipe(p) >= 0);
    > out = p[1];
    > err = sendfile(out, in, &off, 1024);
    > if (err < 0)
    > perror("sendfile");
    > assert(err == 1024);
    > return 0;
    > }

    I can confirm the behaviour you see, and that it starts occurring from the same
    commit 36e2c7421f02a22 (fs: don't allow splice read/write without explicit ops).

    In my tty case, it is clear that removing the default fallback would cause this
    to fail, but assuming the sendfile() source is on a regular filesystem, I am
    unsure why splice cannot find the appropriate splice_write method. Could be
    connected to the fact that the message from warn_unsupported in fs/splice.c
    outputs "splice write not supported for file (pid: 983819 comm: test-sendfile)",
    i.e. the file path is blank. In my case of directly calling splice on a pty, I
    do see a path such as /ptyp0 in that error before implementing splice_(read/write)
    callbacks. Maybe splice is getting a bogus file pointer from sendfile?

     \ /
      Last update: 2021-01-17 07:16    [W:3.134 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site