From 8b9cb36d1c74f71da5bc70b73330291f1df298ad Mon Sep 17 00:00:00 2001 From: Dean Deng Date: Fri, 28 Aug 2020 11:26:25 -0700 Subject: Fix EOF handling for splice. Also, add corresponding EOF tests for splice/sendfile. Discovered by syzkaller. PiperOrigin-RevId: 328975990 --- pkg/sentry/syscalls/linux/vfs2/splice.go | 7 ++++++- test/syscalls/linux/sendfile.cc | 16 ++++++++++++++++ test/syscalls/linux/splice.cc | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/pkg/sentry/syscalls/linux/vfs2/splice.go b/pkg/sentry/syscalls/linux/vfs2/splice.go index 192411393..68ce94778 100644 --- a/pkg/sentry/syscalls/linux/vfs2/splice.go +++ b/pkg/sentry/syscalls/linux/vfs2/splice.go @@ -141,9 +141,14 @@ func Splice(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal inOffset += n } default: - panic("not possible") + panic("at least one end of splice must be a pipe") } + if n == 0 && err == io.EOF { + // We reached the end of the file. Eat the error and exit the loop. + err = nil + break + } if n != 0 || err != syserror.ErrWouldBlock || nonBlock { break } diff --git a/test/syscalls/linux/sendfile.cc b/test/syscalls/linux/sendfile.cc index e65387f59..a8bfb01f1 100644 --- a/test/syscalls/linux/sendfile.cc +++ b/test/syscalls/linux/sendfile.cc @@ -533,6 +533,22 @@ TEST(SendFileTest, SendPipeWouldBlock) { SyscallFailsWithErrno(EWOULDBLOCK)); } +TEST(SendFileTest, SendPipeEOF) { + // Create and open an empty input file. + const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); + const FileDescriptor inf = + ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); + + // Setup the output named pipe. + int fds[2]; + ASSERT_THAT(pipe2(fds, O_NONBLOCK), SyscallSucceeds()); + const FileDescriptor rfd(fds[0]); + const FileDescriptor wfd(fds[1]); + + EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, 123), + SyscallSucceedsWithValue(0)); +} + TEST(SendFileTest, SendPipeBlocks) { // Create temp file. constexpr char kData[] = diff --git a/test/syscalls/linux/splice.cc b/test/syscalls/linux/splice.cc index be3fb4840..a1d2b9b11 100644 --- a/test/syscalls/linux/splice.cc +++ b/test/syscalls/linux/splice.cc @@ -298,6 +298,23 @@ TEST(SpliceTest, ToPipe) { EXPECT_EQ(memcmp(rbuf.data(), buf.data(), buf.size()), 0); } +TEST(SpliceTest, ToPipeEOF) { + // Create and open an empty input file. + const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); + const FileDescriptor in_fd = + ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); + + // Create a new pipe. + int fds[2]; + ASSERT_THAT(pipe(fds), SyscallSucceeds()); + const FileDescriptor rfd(fds[0]); + const FileDescriptor wfd(fds[1]); + + // Splice from the empty file to the pipe. + EXPECT_THAT(splice(in_fd.get(), nullptr, wfd.get(), nullptr, 123, 0), + SyscallSucceedsWithValue(0)); +} + TEST(SpliceTest, ToPipeOffset) { // Open the input file. const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); -- cgit v1.2.3