• Jann Horn's avatar
    splice: don't merge into linked buffers · ef02f9fe
    Jann Horn authored
    commit a0ce2f0a upstream.
    
    Before this patch, it was possible for two pipes to affect each other after
    data had been transferred between them with tee():
    
    ============
    $ cat tee_test.c
    
    int main(void) {
      int pipe_a[2];
      if (pipe(pipe_a)) err(1, "pipe");
      int pipe_b[2];
      if (pipe(pipe_b)) err(1, "pipe");
      if (write(pipe_a[1], "abcd", 4) != 4) err(1, "write");
      if (tee(pipe_a[0], pipe_b[1], 2, 0) != 2) err(1, "tee");
      if (write(pipe_b[1], "xx", 2) != 2) err(1, "write");
    
      char buf[5];
      if (read(pipe_a[0], buf, 4) != 4) err(1, "read");
      buf[4] = 0;
      printf("got back: '%s'\n", buf);
    }
    $ gcc -o tee_test tee_test.c
    $ ./tee_test
    got back: 'abxx'
    $
    ============
    
    As suggested by Al Viro, fix it by creating a separate type for
    non-mergeable pipe buffers, then changing the types of buffers in
    splice_pipe_to_pipe() and link_pipe().
    
    Cc: <stable@vger.kernel.org>
    Fixes: 7c77f0b3 ("splice: implement pipe to pipe splicing")
    Fixes: 70524490 ("[PATCH] splice: add support for sys_tee()")
    Suggested-by: 's avatarAl Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: 's avatarJann Horn <jannh@google.com>
    Signed-off-by: 's avatarAl Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: 's avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    ef02f9fe
pipe.c 27.2 KB