From ff34288f9248d6dc2fd50416dfd3a399e7477f7b Mon Sep 17 00:00:00 2001 From: Nathan Wang Date: Thu, 1 Feb 2024 05:18:44 +0000 Subject: [PATCH] Fix EOFs when reading from empty canon->noncanon PTY when switching from canonical to non-canonical mode, only mark inQueue as readable if there is input to be read --- pkg/sentry/fsimpl/devpts/line_discipline.go | 2 +- test/syscalls/linux/pty.cc | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/pkg/sentry/fsimpl/devpts/line_discipline.go b/pkg/sentry/fsimpl/devpts/line_discipline.go index 714554c8c..26ba4d85a 100644 --- a/pkg/sentry/fsimpl/devpts/line_discipline.go +++ b/pkg/sentry/fsimpl/devpts/line_discipline.go @@ -154,7 +154,7 @@ func (l *lineDiscipline) setTermios(task *kernel.Task, args arch.SyscallArgument if oldCanonEnabled && !l.termios.LEnabled(linux.ICANON) { l.inQueue.mu.Lock() l.inQueue.pushWaitBufLocked(l) - l.inQueue.readable = true + l.inQueue.readable = len(l.inQueue.readBuf) > 0 l.inQueue.mu.Unlock() l.termiosMu.Unlock() l.replicaWaiter.Notify(waiter.ReadableEvents) diff --git a/test/syscalls/linux/pty.cc b/test/syscalls/linux/pty.cc index 1a75e587c..1cee2a551 100644 --- a/test/syscalls/linux/pty.cc +++ b/test/syscalls/linux/pty.cc @@ -1152,6 +1152,23 @@ TEST_F(PtyTest, SwitchNoncanonToCanonNoNewlineBig) { ExpectFinished(replica_); } +// If the canonical input buffer is empty, and we switch to non-canonical +// mode, the input buffer should not be readable. +TEST_F(PtyTest, SwitchCanonToNoncanonEmptyInput) { + constexpr char kInput[] = ""; + ASSERT_THAT(WriteFd(master_.get(), kInput, sizeof(kInput)), + SyscallSucceedsWithValue(sizeof(kInput))); + + DisableCanonical(); + + // Nothing available yet. + char buf[2] = {}; + ASSERT_THAT(PollAndReadFd(replica_.get(), buf, 2, kTimeoutShort), + PosixErrorIs(ETIMEDOUT, ::testing::StrEq("Poll timed out"))); + + ExpectFinished(replica_); +} + // Tests that we can write over the 4095 noncanonical limit, then read out // everything. TEST_F(PtyTest, NoncanonBigWrite) {