summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@google.com>2021-02-09 01:32:55 -0800
committergVisor bot <gvisor-bot@google.com>2021-02-09 01:34:45 -0800
commitd6dbe6e5ca5445dac278d3b6654af8d13379878a (patch)
tree7532e7095ec8988b5bed59c3ebb2e8b156eaabbd
parent3f802e7180cfe703ecb97d8f2b6ba32257cf6216 (diff)
pipe: writeLocked has to return ErrWouldBlock if the pipe is full
PiperOrigin-RevId: 356450303
-rw-r--r--pkg/sentry/fsimpl/tmpfs/regular_file.go3
-rw-r--r--pkg/sentry/kernel/pipe/pipe.go8
-rw-r--r--test/syscalls/linux/sendfile.cc23
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[] =