diff options
author | Andrei Vagin <avagin@google.com> | 2021-02-09 01:32:55 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-02-09 01:34:45 -0800 |
commit | d6dbe6e5ca5445dac278d3b6654af8d13379878a (patch) | |
tree | 7532e7095ec8988b5bed59c3ebb2e8b156eaabbd | |
parent | 3f802e7180cfe703ecb97d8f2b6ba32257cf6216 (diff) |
pipe: writeLocked has to return ErrWouldBlock if the pipe is full
PiperOrigin-RevId: 356450303
-rw-r--r-- | pkg/sentry/fsimpl/tmpfs/regular_file.go | 3 | ||||
-rw-r--r-- | pkg/sentry/kernel/pipe/pipe.go | 8 | ||||
-rw-r--r-- | test/syscalls/linux/sendfile.cc | 23 |
3 files changed, 32 insertions, 2 deletions
diff --git a/pkg/sentry/fsimpl/tmpfs/regular_file.go b/pkg/sentry/fsimpl/tmpfs/regular_file.go index 6255a7c84..82a743ff3 100644 --- a/pkg/sentry/fsimpl/tmpfs/regular_file.go +++ b/pkg/sentry/fsimpl/tmpfs/regular_file.go @@ -656,6 +656,9 @@ func (rw *regularFileReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, // Write to that memory as usual. seg, gap = rw.file.data.Insert(gap, gapMR, fr.Start), fsutil.FileRangeGapIterator{} + + default: + panic("unreachable") } } exitLoop: diff --git a/pkg/sentry/kernel/pipe/pipe.go b/pkg/sentry/kernel/pipe/pipe.go index c551acd99..2c8668fc4 100644 --- a/pkg/sentry/kernel/pipe/pipe.go +++ b/pkg/sentry/kernel/pipe/pipe.go @@ -247,11 +247,15 @@ func (p *Pipe) writeLocked(count int64, f func(safemem.BlockSeq) (uint64, error) return 0, syscall.EPIPE } - // POSIX requires that a write smaller than atomicIOBytes (PIPE_BUF) be - // atomic, but requires no atomicity for writes larger than this. avail := p.max - p.size + if avail == 0 { + return 0, syserror.ErrWouldBlock + } short := false if count > avail { + // POSIX requires that a write smaller than atomicIOBytes + // (PIPE_BUF) be atomic, but requires no atomicity for writes + // larger than this. if count <= atomicIOBytes { return 0, syserror.ErrWouldBlock } diff --git a/test/syscalls/linux/sendfile.cc b/test/syscalls/linux/sendfile.cc index 3924e0001..93b3a94f1 100644 --- a/test/syscalls/linux/sendfile.cc +++ b/test/syscalls/linux/sendfile.cc @@ -551,6 +551,29 @@ TEST(SendFileTest, SendPipeEOF) { SyscallSucceedsWithValue(0)); } +TEST(SendFileTest, SendToFullPipeReturnsEAGAIN) { + // 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_RDWR)); + + // Set up the output pipe. + int fds[2]; + ASSERT_THAT(pipe2(fds, O_NONBLOCK), SyscallSucceeds()); + const FileDescriptor rfd(fds[0]); + const FileDescriptor wfd(fds[1]); + + int pipe_size = -1; + ASSERT_THAT(pipe_size = fcntl(wfd.get(), F_GETPIPE_SZ), SyscallSucceeds()); + int data_size = pipe_size * 8; + ASSERT_THAT(ftruncate(in_fd.get(), data_size), SyscallSucceeds()); + + ASSERT_THAT(sendfile(wfd.get(), in_fd.get(), 0, data_size), + SyscallSucceeds()); + EXPECT_THAT(sendfile(wfd.get(), in_fd.get(), 0, data_size), + SyscallFailsWithErrno(EAGAIN)); +} + TEST(SendFileTest, SendPipeBlocks) { // Create temp file. constexpr char kData[] = |