]> git.ipfire.org Git - thirdparty/kernel/stable.git/commit
splice: don't merge into linked buffers
authorJann Horn <jannh@google.com>
Wed, 23 Jan 2019 14:19:17 +0000 (15:19 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 23 Mar 2019 19:09:59 +0000 (20:09 +0100)
commit2af926fd52fc287a92fc782ce074f349d86966aa
tree0d57a0d79c7b30cc3602b66b21ee8b9879e2ee42
parent1c2123ff43122bb9e0578198391ee3cf752049d6
splice: don't merge into linked buffers

commit a0ce2f0aa6ad97c3d4927bf2ca54bcebdf062d55 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: 7c77f0b3f920 ("splice: implement pipe to pipe splicing")
Fixes: 70524490ee2e ("[PATCH] splice: add support for sys_tee()")
Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/pipe.c
fs/splice.c
include/linux/pipe_fs_i.h