github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/pty.cc (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include <fcntl.h>
    16  #include <linux/capability.h>
    17  #include <linux/major.h>
    18  #include <poll.h>
    19  #include <sched.h>
    20  #include <signal.h>
    21  #include <sys/ioctl.h>
    22  #include <sys/mman.h>
    23  #include <sys/stat.h>
    24  #include <sys/sysmacros.h>
    25  #include <sys/types.h>
    26  #include <sys/wait.h>
    27  #include <termios.h>
    28  #include <unistd.h>
    29  
    30  #include <iostream>
    31  
    32  #include "gtest/gtest.h"
    33  #include "absl/base/macros.h"
    34  #include "absl/strings/str_cat.h"
    35  #include "absl/synchronization/notification.h"
    36  #include "absl/time/clock.h"
    37  #include "absl/time/time.h"
    38  #include "test/util/capability_util.h"
    39  #include "test/util/cleanup.h"
    40  #include "test/util/file_descriptor.h"
    41  #include "test/util/posix_error.h"
    42  #include "test/util/pty_util.h"
    43  #include "test/util/signal_util.h"
    44  #include "test/util/test_util.h"
    45  #include "test/util/thread_util.h"
    46  
    47  namespace gvisor {
    48  namespace testing {
    49  
    50  namespace {
    51  
    52  using ::testing::AnyOf;
    53  using ::testing::Contains;
    54  using ::testing::Eq;
    55  using ::testing::Not;
    56  using SubprocessCallback = std::function<void()>;
    57  
    58  // Tests Unix98 pseudoterminals.
    59  //
    60  // These tests assume that /dev/ptmx exists and is associated with a devpts
    61  // filesystem mounted at /dev/pts/. While a Linux distribution could
    62  // theoretically place those anywhere, glibc expects those locations, so they
    63  // are effectively fixed.
    64  
    65  // Minor device number for an unopened ptmx file.
    66  constexpr int kPtmxMinor = 2;
    67  
    68  // The timeout when polling for data from a pty. When data is written to one end
    69  // of a pty, Linux asynchronously makes it available to the other end, so we
    70  // have to wait.
    71  constexpr absl::Duration kTimeout = absl::Seconds(20);
    72  
    73  // The maximum line size in bytes returned per read from a pty file.
    74  constexpr int kMaxLineSize = 4096;
    75  
    76  constexpr char kMasterPath[] = "/dev/ptmx";
    77  
    78  // glibc defines its own, different, version of struct termios. We care about
    79  // what the kernel does, not glibc.
    80  #define KERNEL_NCCS 19
    81  struct kernel_termios {
    82    tcflag_t c_iflag;
    83    tcflag_t c_oflag;
    84    tcflag_t c_cflag;
    85    tcflag_t c_lflag;
    86    cc_t c_line;
    87    cc_t c_cc[KERNEL_NCCS];
    88  };
    89  
    90  bool operator==(struct kernel_termios const& a,
    91                  struct kernel_termios const& b) {
    92    return memcmp(&a, &b, sizeof(a)) == 0;
    93  }
    94  
    95  // Returns the termios-style control character for the passed character.
    96  //
    97  // e.g., for Ctrl-C, i.e., ^C, call ControlCharacter('C').
    98  //
    99  // Standard control characters are ASCII bytes 0 through 31.
   100  constexpr char ControlCharacter(char c) {
   101    // A is 1, B is 2, etc.
   102    return c - 'A' + 1;
   103  }
   104  
   105  // Returns the printable character the given control character represents.
   106  constexpr char FromControlCharacter(char c) { return c + 'A' - 1; }
   107  
   108  // Returns true if c is a control character.
   109  //
   110  // Standard control characters are ASCII bytes 0 through 31.
   111  constexpr bool IsControlCharacter(char c) { return c <= 31; }
   112  
   113  struct Field {
   114    const char* name;
   115    uint64_t mask;
   116    uint64_t value;
   117  };
   118  
   119  // ParseFields returns a string representation of value, using the names in
   120  // fields.
   121  std::string ParseFields(const Field* fields, size_t len, uint64_t value) {
   122    bool first = true;
   123    std::string s;
   124    for (size_t i = 0; i < len; i++) {
   125      const Field f = fields[i];
   126      if ((value & f.mask) == f.value) {
   127        if (!first) {
   128          s += "|";
   129        }
   130        s += f.name;
   131        first = false;
   132        value &= ~f.mask;
   133      }
   134    }
   135  
   136    if (value) {
   137      if (!first) {
   138        s += "|";
   139      }
   140      absl::StrAppend(&s, value);
   141    }
   142  
   143    return s;
   144  }
   145  
   146  const Field kIflagFields[] = {
   147      {"IGNBRK", IGNBRK, IGNBRK}, {"BRKINT", BRKINT, BRKINT},
   148      {"IGNPAR", IGNPAR, IGNPAR}, {"PARMRK", PARMRK, PARMRK},
   149      {"INPCK", INPCK, INPCK},    {"ISTRIP", ISTRIP, ISTRIP},
   150      {"INLCR", INLCR, INLCR},    {"IGNCR", IGNCR, IGNCR},
   151      {"ICRNL", ICRNL, ICRNL},    {"IUCLC", IUCLC, IUCLC},
   152      {"IXON", IXON, IXON},       {"IXANY", IXANY, IXANY},
   153      {"IXOFF", IXOFF, IXOFF},    {"IMAXBEL", IMAXBEL, IMAXBEL},
   154      {"IUTF8", IUTF8, IUTF8},
   155  };
   156  
   157  const Field kOflagFields[] = {
   158      {"OPOST", OPOST, OPOST}, {"OLCUC", OLCUC, OLCUC},
   159      {"ONLCR", ONLCR, ONLCR}, {"OCRNL", OCRNL, OCRNL},
   160      {"ONOCR", ONOCR, ONOCR}, {"ONLRET", ONLRET, ONLRET},
   161      {"OFILL", OFILL, OFILL}, {"OFDEL", OFDEL, OFDEL},
   162      {"NL0", NLDLY, NL0},     {"NL1", NLDLY, NL1},
   163      {"CR0", CRDLY, CR0},     {"CR1", CRDLY, CR1},
   164      {"CR2", CRDLY, CR2},     {"CR3", CRDLY, CR3},
   165      {"TAB0", TABDLY, TAB0},  {"TAB1", TABDLY, TAB1},
   166      {"TAB2", TABDLY, TAB2},  {"TAB3", TABDLY, TAB3},
   167      {"BS0", BSDLY, BS0},     {"BS1", BSDLY, BS1},
   168      {"FF0", FFDLY, FF0},     {"FF1", FFDLY, FF1},
   169      {"VT0", VTDLY, VT0},     {"VT1", VTDLY, VT1},
   170      {"XTABS", XTABS, XTABS},
   171  };
   172  
   173  #ifndef IBSHIFT
   174  // Shift from CBAUD to CIBAUD.
   175  #define IBSHIFT 16
   176  #endif
   177  
   178  const Field kCflagFields[] = {
   179      {"B0", CBAUD, B0},
   180      {"B50", CBAUD, B50},
   181      {"B75", CBAUD, B75},
   182      {"B110", CBAUD, B110},
   183      {"B134", CBAUD, B134},
   184      {"B150", CBAUD, B150},
   185      {"B200", CBAUD, B200},
   186      {"B300", CBAUD, B300},
   187      {"B600", CBAUD, B600},
   188      {"B1200", CBAUD, B1200},
   189      {"B1800", CBAUD, B1800},
   190      {"B2400", CBAUD, B2400},
   191      {"B4800", CBAUD, B4800},
   192      {"B9600", CBAUD, B9600},
   193      {"B19200", CBAUD, B19200},
   194      {"B38400", CBAUD, B38400},
   195      {"CS5", CSIZE, CS5},
   196      {"CS6", CSIZE, CS6},
   197      {"CS7", CSIZE, CS7},
   198      {"CS8", CSIZE, CS8},
   199      {"CSTOPB", CSTOPB, CSTOPB},
   200      {"CREAD", CREAD, CREAD},
   201      {"PARENB", PARENB, PARENB},
   202      {"PARODD", PARODD, PARODD},
   203      {"HUPCL", HUPCL, HUPCL},
   204      {"CLOCAL", CLOCAL, CLOCAL},
   205      {"B57600", CBAUD, B57600},
   206      {"B115200", CBAUD, B115200},
   207      {"B230400", CBAUD, B230400},
   208      {"B460800", CBAUD, B460800},
   209      {"B500000", CBAUD, B500000},
   210      {"B576000", CBAUD, B576000},
   211      {"B921600", CBAUD, B921600},
   212      {"B1000000", CBAUD, B1000000},
   213      {"B1152000", CBAUD, B1152000},
   214      {"B1500000", CBAUD, B1500000},
   215      {"B2000000", CBAUD, B2000000},
   216      {"B2500000", CBAUD, B2500000},
   217      {"B3000000", CBAUD, B3000000},
   218      {"B3500000", CBAUD, B3500000},
   219      {"B4000000", CBAUD, B4000000},
   220      {"CMSPAR", CMSPAR, CMSPAR},
   221      {"CRTSCTS", CRTSCTS, CRTSCTS},
   222      {"IB0", CIBAUD, B0 << IBSHIFT},
   223      {"IB50", CIBAUD, B50 << IBSHIFT},
   224      {"IB75", CIBAUD, B75 << IBSHIFT},
   225      {"IB110", CIBAUD, B110 << IBSHIFT},
   226      {"IB134", CIBAUD, B134 << IBSHIFT},
   227      {"IB150", CIBAUD, B150 << IBSHIFT},
   228      {"IB200", CIBAUD, B200 << IBSHIFT},
   229      {"IB300", CIBAUD, B300 << IBSHIFT},
   230      {"IB600", CIBAUD, B600 << IBSHIFT},
   231      {"IB1200", CIBAUD, B1200 << IBSHIFT},
   232      {"IB1800", CIBAUD, B1800 << IBSHIFT},
   233      {"IB2400", CIBAUD, B2400 << IBSHIFT},
   234      {"IB4800", CIBAUD, B4800 << IBSHIFT},
   235      {"IB9600", CIBAUD, B9600 << IBSHIFT},
   236      {"IB19200", CIBAUD, B19200 << IBSHIFT},
   237      {"IB38400", CIBAUD, B38400 << IBSHIFT},
   238      {"IB57600", CIBAUD, B57600 << IBSHIFT},
   239      {"IB115200", CIBAUD, B115200 << IBSHIFT},
   240      {"IB230400", CIBAUD, B230400 << IBSHIFT},
   241      {"IB460800", CIBAUD, B460800 << IBSHIFT},
   242      {"IB500000", CIBAUD, B500000 << IBSHIFT},
   243      {"IB576000", CIBAUD, B576000 << IBSHIFT},
   244      {"IB921600", CIBAUD, B921600 << IBSHIFT},
   245      {"IB1000000", CIBAUD, B1000000 << IBSHIFT},
   246      {"IB1152000", CIBAUD, B1152000 << IBSHIFT},
   247      {"IB1500000", CIBAUD, B1500000 << IBSHIFT},
   248      {"IB2000000", CIBAUD, B2000000 << IBSHIFT},
   249      {"IB2500000", CIBAUD, B2500000 << IBSHIFT},
   250      {"IB3000000", CIBAUD, B3000000 << IBSHIFT},
   251      {"IB3500000", CIBAUD, B3500000 << IBSHIFT},
   252      {"IB4000000", CIBAUD, B4000000 << IBSHIFT},
   253  };
   254  
   255  const Field kLflagFields[] = {
   256      {"ISIG", ISIG, ISIG},          {"ICANON", ICANON, ICANON},
   257      {"XCASE", XCASE, XCASE},       {"ECHO", ECHO, ECHO},
   258      {"ECHOE", ECHOE, ECHOE},       {"ECHOK", ECHOK, ECHOK},
   259      {"ECHONL", ECHONL, ECHONL},    {"NOFLSH", NOFLSH, NOFLSH},
   260      {"TOSTOP", TOSTOP, TOSTOP},    {"ECHOCTL", ECHOCTL, ECHOCTL},
   261      {"ECHOPRT", ECHOPRT, ECHOPRT}, {"ECHOKE", ECHOKE, ECHOKE},
   262      {"FLUSHO", FLUSHO, FLUSHO},    {"PENDIN", PENDIN, PENDIN},
   263      {"IEXTEN", IEXTEN, IEXTEN},    {"EXTPROC", EXTPROC, EXTPROC},
   264  };
   265  
   266  std::string FormatCC(char c) {
   267    if (isgraph(c)) {
   268      return std::string(1, c);
   269    } else if (c == ' ') {
   270      return " ";
   271    } else if (c == '\t') {
   272      return "\\t";
   273    } else if (c == '\r') {
   274      return "\\r";
   275    } else if (c == '\n') {
   276      return "\\n";
   277    } else if (c == '\0') {
   278      return "\\0";
   279    } else if (IsControlCharacter(c)) {
   280      return absl::StrCat("^", std::string(1, FromControlCharacter(c)));
   281    }
   282    return absl::StrCat("\\x", absl::Hex(c));
   283  }
   284  
   285  std::ostream& operator<<(std::ostream& os, struct kernel_termios const& a) {
   286    os << "{ c_iflag = "
   287       << ParseFields(kIflagFields, ABSL_ARRAYSIZE(kIflagFields), a.c_iflag);
   288    os << ", c_oflag = "
   289       << ParseFields(kOflagFields, ABSL_ARRAYSIZE(kOflagFields), a.c_oflag);
   290    os << ", c_cflag = "
   291       << ParseFields(kCflagFields, ABSL_ARRAYSIZE(kCflagFields), a.c_cflag);
   292    os << ", c_lflag = "
   293       << ParseFields(kLflagFields, ABSL_ARRAYSIZE(kLflagFields), a.c_lflag);
   294    os << ", c_line = " << a.c_line;
   295    os << ", c_cc = { [VINTR] = '" << FormatCC(a.c_cc[VINTR]);
   296    os << "', [VQUIT] = '" << FormatCC(a.c_cc[VQUIT]);
   297    os << "', [VERASE] = '" << FormatCC(a.c_cc[VERASE]);
   298    os << "', [VKILL] = '" << FormatCC(a.c_cc[VKILL]);
   299    os << "', [VEOF] = '" << FormatCC(a.c_cc[VEOF]);
   300    os << "', [VTIME] = '" << static_cast<int>(a.c_cc[VTIME]);
   301    os << "', [VMIN] = " << static_cast<int>(a.c_cc[VMIN]);
   302    os << ", [VSWTC] = '" << FormatCC(a.c_cc[VSWTC]);
   303    os << "', [VSTART] = '" << FormatCC(a.c_cc[VSTART]);
   304    os << "', [VSTOP] = '" << FormatCC(a.c_cc[VSTOP]);
   305    os << "', [VSUSP] = '" << FormatCC(a.c_cc[VSUSP]);
   306    os << "', [VEOL] = '" << FormatCC(a.c_cc[VEOL]);
   307    os << "', [VREPRINT] = '" << FormatCC(a.c_cc[VREPRINT]);
   308    os << "', [VDISCARD] = '" << FormatCC(a.c_cc[VDISCARD]);
   309    os << "', [VWERASE] = '" << FormatCC(a.c_cc[VWERASE]);
   310    os << "', [VLNEXT] = '" << FormatCC(a.c_cc[VLNEXT]);
   311    os << "', [VEOL2] = '" << FormatCC(a.c_cc[VEOL2]);
   312    os << "'}";
   313    return os;
   314  }
   315  
   316  // Return the default termios settings for a new terminal.
   317  struct kernel_termios DefaultTermios() {
   318    struct kernel_termios t = {};
   319    t.c_iflag = IXON | ICRNL;
   320    t.c_oflag = OPOST | ONLCR;
   321    t.c_cflag = B38400 | CSIZE | CS8 | CREAD;
   322    t.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
   323    t.c_line = 0;
   324    t.c_cc[VINTR] = ControlCharacter('C');
   325    t.c_cc[VQUIT] = ControlCharacter('\\');
   326    t.c_cc[VERASE] = '\x7f';
   327    t.c_cc[VKILL] = ControlCharacter('U');
   328    t.c_cc[VEOF] = ControlCharacter('D');
   329    t.c_cc[VTIME] = '\0';
   330    t.c_cc[VMIN] = 1;
   331    t.c_cc[VSWTC] = '\0';
   332    t.c_cc[VSTART] = ControlCharacter('Q');
   333    t.c_cc[VSTOP] = ControlCharacter('S');
   334    t.c_cc[VSUSP] = ControlCharacter('Z');
   335    t.c_cc[VEOL] = '\0';
   336    t.c_cc[VREPRINT] = ControlCharacter('R');
   337    t.c_cc[VDISCARD] = ControlCharacter('O');
   338    t.c_cc[VWERASE] = ControlCharacter('W');
   339    t.c_cc[VLNEXT] = ControlCharacter('V');
   340    t.c_cc[VEOL2] = '\0';
   341    return t;
   342  }
   343  
   344  // PollAndReadFd tries to read count bytes from buf within timeout.
   345  //
   346  // Returns a partial read if some bytes were read.
   347  //
   348  // fd must be non-blocking.
   349  PosixErrorOr<size_t> PollAndReadFd(int fd, void* buf, size_t count,
   350                                     absl::Duration timeout) {
   351    absl::Time end = absl::Now() + timeout;
   352  
   353    size_t completed = 0;
   354    absl::Duration remaining;
   355    while ((remaining = end - absl::Now()) > absl::ZeroDuration()) {
   356      struct pollfd pfd = {fd, POLLIN, 0};
   357      int ret = RetryEINTR(poll)(&pfd, 1, absl::ToInt64Milliseconds(remaining));
   358      if (ret < 0) {
   359        return PosixError(errno, "poll failed");
   360      } else if (ret == 0) {
   361        // Timed out.
   362        continue;
   363      } else if (ret != 1) {
   364        return PosixError(EINVAL, absl::StrCat("Bad poll ret ", ret));
   365      }
   366  
   367      ssize_t n =
   368          ReadFd(fd, static_cast<char*>(buf) + completed, count - completed);
   369      if (n < 0) {
   370        if (errno == EAGAIN) {
   371          // Linux sometimes returns EAGAIN from this read, despite the fact that
   372          // poll returned success. Let's just do what do as we are told and try
   373          // again.
   374          continue;
   375        }
   376        return PosixError(errno, "read failed");
   377      }
   378      completed += n;
   379      if (completed >= count) {
   380        return completed;
   381      }
   382    }
   383  
   384    if (completed) {
   385      return completed;
   386    }
   387    return PosixError(ETIMEDOUT, "Poll timed out");
   388  }
   389  
   390  TEST(PtyTrunc, Truncate) {
   391    SKIP_IF(IsRunningWithVFS1());
   392  
   393    // setsid either puts us in a new session or fails because we're already the
   394    // session leader. Either way, this ensures we're the session leader and have
   395    // no controlling terminal.
   396    ASSERT_THAT(setsid(), AnyOf(SyscallSucceeds(), SyscallFailsWithErrno(EPERM)));
   397  
   398    // Make sure we're ignoring SIGHUP, which will be sent to this process once we
   399    // disconnect the TTY.
   400    struct sigaction sa = {};
   401    sa.sa_handler = SIG_IGN;
   402    sa.sa_flags = 0;
   403    sigemptyset(&sa.sa_mask);
   404    const Cleanup cleanup =
   405        ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGHUP, sa));
   406  
   407    // Opening PTYs with O_TRUNC shouldn't cause an error, but calls to
   408    // (f)truncate should.
   409    FileDescriptor master =
   410        ASSERT_NO_ERRNO_AND_VALUE(Open(kMasterPath, O_RDWR | O_TRUNC));
   411    int n = ASSERT_NO_ERRNO_AND_VALUE(ReplicaID(master));
   412    std::string spath = absl::StrCat("/dev/pts/", n);
   413    FileDescriptor replica =
   414        ASSERT_NO_ERRNO_AND_VALUE(Open(spath, O_RDWR | O_NONBLOCK | O_TRUNC));
   415    ASSERT_THAT(ioctl(replica.get(), TIOCNOTTY), SyscallSucceeds());
   416  
   417    EXPECT_THAT(truncate(kMasterPath, 0), SyscallFailsWithErrno(EINVAL));
   418    EXPECT_THAT(truncate(spath.c_str(), 0), SyscallFailsWithErrno(EINVAL));
   419    EXPECT_THAT(ftruncate(master.get(), 0), SyscallFailsWithErrno(EINVAL));
   420    EXPECT_THAT(ftruncate(replica.get(), 0), SyscallFailsWithErrno(EINVAL));
   421  }
   422  
   423  TEST(BasicPtyTest, StatUnopenedMaster) {
   424    struct stat s;
   425    ASSERT_THAT(stat(kMasterPath, &s), SyscallSucceeds());
   426  
   427    EXPECT_EQ(s.st_rdev, makedev(TTYAUX_MAJOR, kPtmxMinor));
   428    EXPECT_EQ(s.st_size, 0);
   429    EXPECT_EQ(s.st_blocks, 0);
   430  
   431    // ptmx attached to a specific devpts mount uses block size 1024. See
   432    // fs/devpts/inode.c:devpts_fill_super.
   433    //
   434    // The global ptmx device uses the block size of the filesystem it is created
   435    // on (which is usually 4096 for disk filesystems).
   436    EXPECT_THAT(s.st_blksize, AnyOf(Eq(1024), Eq(4096)));
   437  }
   438  
   439  // Waits for count bytes to be readable from fd. Unlike poll, which can return
   440  // before all data is moved into a pty's read buffer, this function waits for
   441  // all count bytes to become readable.
   442  PosixErrorOr<int> WaitUntilReceived(int fd, int count) {
   443    int buffered = -1;
   444    absl::Duration remaining;
   445    absl::Time end = absl::Now() + kTimeout;
   446    while ((remaining = end - absl::Now()) > absl::ZeroDuration()) {
   447      if (ioctl(fd, FIONREAD, &buffered) < 0) {
   448        return PosixError(errno, "failed FIONREAD ioctl");
   449      }
   450      if (buffered >= count) {
   451        return buffered;
   452      }
   453      absl::SleepFor(absl::Milliseconds(500));
   454    }
   455    return PosixError(
   456        ETIMEDOUT,
   457        absl::StrFormat(
   458            "FIONREAD timed out, receiving only %d of %d expected bytes",
   459            buffered, count));
   460  }
   461  
   462  // Verifies that there is nothing left to read from fd.
   463  void ExpectFinished(const FileDescriptor& fd) {
   464    // Nothing more to read.
   465    char c;
   466    EXPECT_THAT(ReadFd(fd.get(), &c, 1), SyscallFailsWithErrno(EAGAIN));
   467  }
   468  
   469  // Verifies that we can read expected bytes from fd into buf.
   470  void ExpectReadable(const FileDescriptor& fd, int expected, char* buf) {
   471    size_t n = ASSERT_NO_ERRNO_AND_VALUE(
   472        PollAndReadFd(fd.get(), buf, expected, kTimeout));
   473    EXPECT_EQ(expected, n);
   474  }
   475  
   476  TEST(BasicPtyTest, OpenMasterReplica) {
   477    FileDescriptor master = ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/ptmx", O_RDWR));
   478    FileDescriptor replica = ASSERT_NO_ERRNO_AND_VALUE(OpenReplica(master));
   479  }
   480  
   481  TEST(BasicPtyTest, OpenSetsControllingTTY) {
   482    SKIP_IF(IsRunningWithVFS1());
   483    // setsid either puts us in a new session or fails because we're already the
   484    // session leader. Either way, this ensures we're the session leader.
   485    ASSERT_THAT(setsid(), AnyOf(SyscallSucceeds(), SyscallFailsWithErrno(EPERM)));
   486  
   487    // Make sure we're ignoring SIGHUP, which will be sent to this process once we
   488    // disconnect the TTY.
   489    struct sigaction sa = {};
   490    sa.sa_handler = SIG_IGN;
   491    sa.sa_flags = 0;
   492    sigemptyset(&sa.sa_mask);
   493    struct sigaction old_sa;
   494    ASSERT_THAT(sigaction(SIGHUP, &sa, &old_sa), SyscallSucceeds());
   495    auto cleanup = Cleanup([old_sa] {
   496      EXPECT_THAT(sigaction(SIGHUP, &old_sa, NULL), SyscallSucceeds());
   497    });
   498  
   499    FileDescriptor master = ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/ptmx", O_RDWR));
   500    FileDescriptor replica =
   501        ASSERT_NO_ERRNO_AND_VALUE(OpenReplica(master, O_NONBLOCK | O_RDWR));
   502  
   503    // Opening replica should make it our controlling TTY, and therefore we are
   504    // able to give it up.
   505    ASSERT_THAT(ioctl(replica.get(), TIOCNOTTY), SyscallSucceeds());
   506  }
   507  
   508  TEST(BasicPtyTest, OpenMasterDoesNotSetsControllingTTY) {
   509    SKIP_IF(IsRunningWithVFS1());
   510    // setsid either puts us in a new session or fails because we're already the
   511    // session leader. Either way, this ensures we're the session leader.
   512    ASSERT_THAT(setsid(), AnyOf(SyscallSucceeds(), SyscallFailsWithErrno(EPERM)));
   513    FileDescriptor master = ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/ptmx", O_RDWR));
   514  
   515    // Opening master does not set the controlling TTY, and therefore we are
   516    // unable to give it up.
   517    ASSERT_THAT(ioctl(master.get(), TIOCNOTTY), SyscallFailsWithErrno(ENOTTY));
   518  }
   519  
   520  TEST(BasicPtyTest, OpenNOCTTY) {
   521    SKIP_IF(IsRunningWithVFS1());
   522    // setsid either puts us in a new session or fails because we're already the
   523    // session leader. Either way, this ensures we're the session leader.
   524    ASSERT_THAT(setsid(), AnyOf(SyscallSucceeds(), SyscallFailsWithErrno(EPERM)));
   525    FileDescriptor master = ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/ptmx", O_RDWR));
   526    FileDescriptor replica = ASSERT_NO_ERRNO_AND_VALUE(
   527        OpenReplica(master, O_NOCTTY | O_NONBLOCK | O_RDWR));
   528  
   529    // Opening replica with O_NOCTTY won't make it our controlling TTY, and
   530    // therefore we are unable to give it up.
   531    ASSERT_THAT(ioctl(replica.get(), TIOCNOTTY), SyscallFailsWithErrno(ENOTTY));
   532  }
   533  
   534  // The replica entry in /dev/pts/ disappears when the master is closed, even if
   535  // the replica is still open.
   536  TEST(BasicPtyTest, ReplicaEntryGoneAfterMasterClose) {
   537    FileDescriptor master = ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/ptmx", O_RDWR));
   538    FileDescriptor replica = ASSERT_NO_ERRNO_AND_VALUE(OpenReplica(master));
   539  
   540    // Get pty index.
   541    int index = -1;
   542    ASSERT_THAT(ioctl(master.get(), TIOCGPTN, &index), SyscallSucceeds());
   543  
   544    std::string path = absl::StrCat("/dev/pts/", index);
   545  
   546    struct stat st;
   547    EXPECT_THAT(stat(path.c_str(), &st), SyscallSucceeds());
   548  
   549    master.reset();
   550  
   551    EXPECT_THAT(stat(path.c_str(), &st), SyscallFailsWithErrno(ENOENT));
   552  }
   553  
   554  TEST(BasicPtyTest, Getdents) {
   555    FileDescriptor master1 = ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/ptmx", O_RDWR));
   556    int index1 = -1;
   557    ASSERT_THAT(ioctl(master1.get(), TIOCGPTN, &index1), SyscallSucceeds());
   558    FileDescriptor replica1 = ASSERT_NO_ERRNO_AND_VALUE(OpenReplica(master1));
   559  
   560    FileDescriptor master2 = ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/ptmx", O_RDWR));
   561    int index2 = -1;
   562    ASSERT_THAT(ioctl(master2.get(), TIOCGPTN, &index2), SyscallSucceeds());
   563    FileDescriptor replica2 = ASSERT_NO_ERRNO_AND_VALUE(OpenReplica(master2));
   564  
   565    // The directory contains ptmx, index1, and index2. (Plus any additional PTYs
   566    // unrelated to this test.)
   567  
   568    std::vector<std::string> contents =
   569        ASSERT_NO_ERRNO_AND_VALUE(ListDir("/dev/pts/", true));
   570    EXPECT_THAT(contents, Contains(absl::StrCat(index1)));
   571    EXPECT_THAT(contents, Contains(absl::StrCat(index2)));
   572  
   573    master2.reset();
   574  
   575    // The directory contains ptmx and index1, but not index2 since the master is
   576    // closed. (Plus any additional PTYs unrelated to this test.)
   577  
   578    contents = ASSERT_NO_ERRNO_AND_VALUE(ListDir("/dev/pts/", true));
   579    EXPECT_THAT(contents, Contains(absl::StrCat(index1)));
   580    EXPECT_THAT(contents, Not(Contains(absl::StrCat(index2))));
   581  
   582    // N.B. devpts supports legacy "single-instance" mode and new "multi-instance"
   583    // mode. In legacy mode, devpts does not contain a "ptmx" device (the distro
   584    // must use mknod to create it somewhere, presumably /dev/ptmx).
   585    // Multi-instance mode does include a "ptmx" device tied to that mount.
   586    //
   587    // We don't check for the presence or absence of "ptmx", as distros vary in
   588    // their usage of the two modes.
   589  }
   590  
   591  class PtyTest : public ::testing::Test {
   592   protected:
   593    void SetUp() override {
   594      master_ = ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/ptmx", O_RDWR | O_NONBLOCK));
   595      replica_ = ASSERT_NO_ERRNO_AND_VALUE(OpenReplica(master_));
   596    }
   597  
   598    void DisableCanonical() {
   599      struct kernel_termios t = {};
   600      EXPECT_THAT(ioctl(replica_.get(), TCGETS, &t), SyscallSucceeds());
   601      t.c_lflag &= ~ICANON;
   602      EXPECT_THAT(ioctl(replica_.get(), TCSETS, &t), SyscallSucceeds());
   603    }
   604  
   605    void EnableCanonical() {
   606      struct kernel_termios t = {};
   607      EXPECT_THAT(ioctl(replica_.get(), TCGETS, &t), SyscallSucceeds());
   608      t.c_lflag |= ICANON;
   609      EXPECT_THAT(ioctl(replica_.get(), TCSETS, &t), SyscallSucceeds());
   610    }
   611  
   612    // Master and replica ends of the PTY. Non-blocking.
   613    FileDescriptor master_;
   614    FileDescriptor replica_;
   615  };
   616  
   617  // Master to replica sanity test.
   618  TEST_F(PtyTest, WriteMasterToReplica) {
   619    // N.B. by default, the replica reads nothing until the master writes a
   620    // newline.
   621    constexpr char kBuf[] = "hello\n";
   622  
   623    EXPECT_THAT(WriteFd(master_.get(), kBuf, sizeof(kBuf) - 1),
   624                SyscallSucceedsWithValue(sizeof(kBuf) - 1));
   625  
   626    // Linux moves data from the master to the replica via async work scheduled
   627    // via tty_flip_buffer_push. Since it is asynchronous, the data may not be
   628    // available for reading immediately. Instead we must poll and assert that it
   629    // becomes available "soon".
   630  
   631    char buf[sizeof(kBuf)] = {};
   632    ExpectReadable(replica_, sizeof(buf) - 1, buf);
   633  
   634    EXPECT_EQ(memcmp(buf, kBuf, sizeof(kBuf)), 0);
   635  }
   636  
   637  // Replica to master sanity test.
   638  TEST_F(PtyTest, WriteReplicaToMaster) {
   639    // N.B. by default, the master reads nothing until the replica writes a
   640    // newline, and the master gets a carriage return.
   641    constexpr char kInput[] = "hello\n";
   642    constexpr char kExpected[] = "hello\r\n";
   643  
   644    EXPECT_THAT(WriteFd(replica_.get(), kInput, sizeof(kInput) - 1),
   645                SyscallSucceedsWithValue(sizeof(kInput) - 1));
   646  
   647    // Linux moves data from the master to the replica via async work scheduled
   648    // via tty_flip_buffer_push. Since it is asynchronous, the data may not be
   649    // available for reading immediately. Instead we must poll and assert that it
   650    // becomes available "soon".
   651  
   652    char buf[sizeof(kExpected)] = {};
   653    ExpectReadable(master_, sizeof(buf) - 1, buf);
   654  
   655    EXPECT_EQ(memcmp(buf, kExpected, sizeof(kExpected)), 0);
   656  }
   657  
   658  TEST_F(PtyTest, WriteInvalidUTF8) {
   659    char c = 0xff;
   660    ASSERT_THAT(syscall(__NR_write, master_.get(), &c, sizeof(c)),
   661                SyscallSucceedsWithValue(sizeof(c)));
   662  }
   663  
   664  // Both the master and replica report the standard default termios settings.
   665  //
   666  // Note that TCGETS on the master actually redirects to the replica (see comment
   667  // on MasterTermiosUnchangable).
   668  TEST_F(PtyTest, DefaultTermios) {
   669    struct kernel_termios t = {};
   670    EXPECT_THAT(ioctl(replica_.get(), TCGETS, &t), SyscallSucceeds());
   671    EXPECT_EQ(t, DefaultTermios());
   672  
   673    EXPECT_THAT(ioctl(master_.get(), TCGETS, &t), SyscallSucceeds());
   674    EXPECT_EQ(t, DefaultTermios());
   675  }
   676  
   677  // Changing termios from the master actually affects the replica.
   678  //
   679  // TCSETS on the master actually redirects to the replica (see comment on
   680  // MasterTermiosUnchangable).
   681  TEST_F(PtyTest, TermiosAffectsReplica) {
   682    struct kernel_termios master_termios = {};
   683    EXPECT_THAT(ioctl(master_.get(), TCGETS, &master_termios), SyscallSucceeds());
   684    master_termios.c_lflag ^= ICANON;
   685    EXPECT_THAT(ioctl(master_.get(), TCSETS, &master_termios), SyscallSucceeds());
   686  
   687    struct kernel_termios replica_termios = {};
   688    EXPECT_THAT(ioctl(replica_.get(), TCGETS, &replica_termios),
   689                SyscallSucceeds());
   690    EXPECT_EQ(master_termios, replica_termios);
   691  }
   692  
   693  // The master end of the pty has termios:
   694  //
   695  // struct kernel_termios t = {
   696  //   .c_iflag = 0;
   697  //   .c_oflag = 0;
   698  //   .c_cflag = B38400 | CS8 | CREAD;
   699  //   .c_lflag = 0;
   700  //   .c_cc = /* same as DefaultTermios */
   701  // }
   702  //
   703  // (From drivers/tty/pty.c:unix98_pty_init)
   704  //
   705  // All termios control ioctls on the master actually redirect to the replica
   706  // (drivers/tty/tty_ioctl.c:tty_mode_ioctl), making it impossible to change the
   707  // master termios.
   708  //
   709  // Verify this by setting ICRNL (which rewrites input \r to \n) and verify that
   710  // it has no effect on the master.
   711  TEST_F(PtyTest, MasterTermiosUnchangable) {
   712    struct kernel_termios master_termios = {};
   713    EXPECT_THAT(ioctl(master_.get(), TCGETS, &master_termios), SyscallSucceeds());
   714    master_termios.c_lflag |= ICRNL;
   715    EXPECT_THAT(ioctl(master_.get(), TCSETS, &master_termios), SyscallSucceeds());
   716  
   717    char c = '\r';
   718    ASSERT_THAT(WriteFd(replica_.get(), &c, 1), SyscallSucceedsWithValue(1));
   719  
   720    ExpectReadable(master_, 1, &c);
   721    EXPECT_EQ(c, '\r');  // ICRNL had no effect!
   722  
   723    ExpectFinished(master_);
   724  }
   725  
   726  // ICRNL rewrites input \r to \n.
   727  TEST_F(PtyTest, TermiosICRNL) {
   728    struct kernel_termios t = DefaultTermios();
   729    t.c_iflag |= ICRNL;
   730    t.c_lflag &= ~ICANON;  // for byte-by-byte reading.
   731    ASSERT_THAT(ioctl(replica_.get(), TCSETS, &t), SyscallSucceeds());
   732  
   733    char c = '\r';
   734    ASSERT_THAT(WriteFd(master_.get(), &c, 1), SyscallSucceedsWithValue(1));
   735  
   736    ExpectReadable(replica_, 1, &c);
   737    EXPECT_EQ(c, '\n');
   738  
   739    ExpectFinished(replica_);
   740  }
   741  
   742  // ONLCR rewrites output \n to \r\n.
   743  TEST_F(PtyTest, TermiosONLCR) {
   744    struct kernel_termios t = DefaultTermios();
   745    t.c_oflag |= ONLCR;
   746    t.c_lflag &= ~ICANON;  // for byte-by-byte reading.
   747    ASSERT_THAT(ioctl(replica_.get(), TCSETS, &t), SyscallSucceeds());
   748  
   749    char c = '\n';
   750    ASSERT_THAT(WriteFd(replica_.get(), &c, 1), SyscallSucceedsWithValue(1));
   751  
   752    // Extra byte for NUL for EXPECT_STREQ.
   753    char buf[3] = {};
   754    ExpectReadable(master_, 2, buf);
   755    EXPECT_STREQ(buf, "\r\n");
   756  
   757    ExpectFinished(replica_);
   758  }
   759  
   760  TEST_F(PtyTest, TermiosIGNCR) {
   761    struct kernel_termios t = DefaultTermios();
   762    t.c_iflag |= IGNCR;
   763    t.c_lflag &= ~ICANON;  // for byte-by-byte reading.
   764    ASSERT_THAT(ioctl(replica_.get(), TCSETS, &t), SyscallSucceeds());
   765  
   766    char c = '\r';
   767    ASSERT_THAT(WriteFd(master_.get(), &c, 1), SyscallSucceedsWithValue(1));
   768  
   769    // Nothing to read.
   770    ASSERT_THAT(PollAndReadFd(replica_.get(), &c, 1, kTimeout),
   771                PosixErrorIs(ETIMEDOUT, ::testing::StrEq("Poll timed out")));
   772  }
   773  
   774  // Test that we can successfully poll for readable data from the replica.
   775  TEST_F(PtyTest, TermiosPollReplica) {
   776    struct kernel_termios t = DefaultTermios();
   777    t.c_iflag |= IGNCR;
   778    t.c_lflag &= ~ICANON;  // for byte-by-byte reading.
   779    ASSERT_THAT(ioctl(replica_.get(), TCSETS, &t), SyscallSucceeds());
   780  
   781    absl::Notification notify;
   782    int sfd = replica_.get();
   783    ScopedThread th([sfd, &notify]() {
   784      notify.Notify();
   785  
   786      // Poll on the reader fd with POLLIN event.
   787      struct pollfd poll_fd = {sfd, POLLIN, 0};
   788      EXPECT_THAT(
   789          RetryEINTR(poll)(&poll_fd, 1, absl::ToInt64Milliseconds(kTimeout)),
   790          SyscallSucceedsWithValue(1));
   791  
   792      // Should trigger POLLIN event.
   793      EXPECT_EQ(poll_fd.revents & POLLIN, POLLIN);
   794    });
   795  
   796    notify.WaitForNotification();
   797    // Sleep ensures that poll begins waiting before we write to the FD.
   798    absl::SleepFor(absl::Seconds(1));
   799  
   800    char s[] = "foo\n";
   801    ASSERT_THAT(WriteFd(master_.get(), s, strlen(s) + 1), SyscallSucceeds());
   802  }
   803  
   804  // Test that we can successfully poll for readable data from the master.
   805  TEST_F(PtyTest, TermiosPollMaster) {
   806    struct kernel_termios t = DefaultTermios();
   807    t.c_iflag |= IGNCR;
   808    t.c_lflag &= ~ICANON;  // for byte-by-byte reading.
   809    ASSERT_THAT(ioctl(master_.get(), TCSETS, &t), SyscallSucceeds());
   810  
   811    absl::Notification notify;
   812    int mfd = master_.get();
   813    ScopedThread th([mfd, &notify]() {
   814      notify.Notify();
   815  
   816      // Poll on the reader fd with POLLIN event.
   817      struct pollfd poll_fd = {mfd, POLLIN, 0};
   818      EXPECT_THAT(
   819          RetryEINTR(poll)(&poll_fd, 1, absl::ToInt64Milliseconds(kTimeout)),
   820          SyscallSucceedsWithValue(1));
   821  
   822      // Should trigger POLLIN event.
   823      EXPECT_EQ(poll_fd.revents & POLLIN, POLLIN);
   824    });
   825  
   826    notify.WaitForNotification();
   827    // Sleep ensures that poll begins waiting before we write to the FD.
   828    absl::SleepFor(absl::Seconds(1));
   829  
   830    char s[] = "foo\n";
   831    ASSERT_THAT(WriteFd(replica_.get(), s, strlen(s) + 1), SyscallSucceeds());
   832  }
   833  
   834  TEST_F(PtyTest, TermiosINLCR) {
   835    struct kernel_termios t = DefaultTermios();
   836    t.c_iflag |= INLCR;
   837    t.c_lflag &= ~ICANON;  // for byte-by-byte reading.
   838    ASSERT_THAT(ioctl(replica_.get(), TCSETS, &t), SyscallSucceeds());
   839  
   840    char c = '\n';
   841    ASSERT_THAT(WriteFd(master_.get(), &c, 1), SyscallSucceedsWithValue(1));
   842  
   843    ExpectReadable(replica_, 1, &c);
   844    EXPECT_EQ(c, '\r');
   845  
   846    ExpectFinished(replica_);
   847  }
   848  
   849  TEST_F(PtyTest, TermiosONOCR) {
   850    struct kernel_termios t = DefaultTermios();
   851    t.c_oflag |= ONOCR;
   852    t.c_lflag &= ~ICANON;  // for byte-by-byte reading.
   853    ASSERT_THAT(ioctl(replica_.get(), TCSETS, &t), SyscallSucceeds());
   854  
   855    // The terminal is at column 0, so there should be no CR to read.
   856    char c = '\r';
   857    ASSERT_THAT(WriteFd(replica_.get(), &c, 1), SyscallSucceedsWithValue(1));
   858  
   859    // Nothing to read.
   860    ASSERT_THAT(PollAndReadFd(master_.get(), &c, 1, kTimeout),
   861                PosixErrorIs(ETIMEDOUT, ::testing::StrEq("Poll timed out")));
   862  
   863    // This time the column is greater than 0, so we should be able to read the CR
   864    // out of the other end.
   865    constexpr char kInput[] = "foo\r";
   866    constexpr int kInputSize = sizeof(kInput) - 1;
   867    ASSERT_THAT(WriteFd(replica_.get(), kInput, kInputSize),
   868                SyscallSucceedsWithValue(kInputSize));
   869  
   870    char buf[kInputSize] = {};
   871    ExpectReadable(master_, kInputSize, buf);
   872  
   873    EXPECT_EQ(memcmp(buf, kInput, kInputSize), 0);
   874  
   875    ExpectFinished(master_);
   876  
   877    // Terminal should be at column 0 again, so no CR can be read.
   878    ASSERT_THAT(WriteFd(replica_.get(), &c, 1), SyscallSucceedsWithValue(1));
   879  
   880    // Nothing to read.
   881    ASSERT_THAT(PollAndReadFd(master_.get(), &c, 1, kTimeout),
   882                PosixErrorIs(ETIMEDOUT, ::testing::StrEq("Poll timed out")));
   883  }
   884  
   885  TEST_F(PtyTest, TermiosOCRNL) {
   886    struct kernel_termios t = DefaultTermios();
   887    t.c_oflag |= OCRNL;
   888    t.c_lflag &= ~ICANON;  // for byte-by-byte reading.
   889    ASSERT_THAT(ioctl(replica_.get(), TCSETS, &t), SyscallSucceeds());
   890  
   891    // The terminal is at column 0, so there should be no CR to read.
   892    char c = '\r';
   893    ASSERT_THAT(WriteFd(replica_.get(), &c, 1), SyscallSucceedsWithValue(1));
   894  
   895    ExpectReadable(master_, 1, &c);
   896    EXPECT_EQ(c, '\n');
   897  
   898    ExpectFinished(master_);
   899  }
   900  
   901  // Tests that VEOL is disabled when we start, and that we can set it to enable
   902  // it.
   903  TEST_F(PtyTest, VEOLTermination) {
   904    // Write a few bytes ending with '\0', and confirm that we can't read.
   905    constexpr char kInput[] = "hello";
   906    ASSERT_THAT(WriteFd(master_.get(), kInput, sizeof(kInput)),
   907                SyscallSucceedsWithValue(sizeof(kInput)));
   908    char buf[sizeof(kInput)] = {};
   909    ASSERT_THAT(PollAndReadFd(replica_.get(), buf, sizeof(kInput), kTimeout),
   910                PosixErrorIs(ETIMEDOUT, ::testing::StrEq("Poll timed out")));
   911  
   912    // Set the EOL character to '=' and write it.
   913    constexpr char delim = '=';
   914    struct kernel_termios t = DefaultTermios();
   915    t.c_cc[VEOL] = delim;
   916    ASSERT_THAT(ioctl(replica_.get(), TCSETS, &t), SyscallSucceeds());
   917    ASSERT_THAT(WriteFd(master_.get(), &delim, 1), SyscallSucceedsWithValue(1));
   918  
   919    // Now we can read, as sending EOL caused the line to become available.
   920    ExpectReadable(replica_, sizeof(kInput), buf);
   921    EXPECT_EQ(memcmp(buf, kInput, sizeof(kInput)), 0);
   922  
   923    ExpectReadable(replica_, 1, buf);
   924    EXPECT_EQ(buf[0], '=');
   925  
   926    ExpectFinished(replica_);
   927  }
   928  
   929  // Tests that we can write more than the 4096 character limit, then a
   930  // terminating character, then read out just the first 4095 bytes plus the
   931  // terminator.
   932  TEST_F(PtyTest, CanonBigWrite) {
   933    constexpr int kWriteLen = kMaxLineSize + 4;
   934    char input[kWriteLen];
   935    memset(input, 'M', kWriteLen - 1);
   936    input[kWriteLen - 1] = '\n';
   937    ASSERT_THAT(WriteFd(master_.get(), input, kWriteLen),
   938                SyscallSucceedsWithValue(kWriteLen));
   939  
   940    // We can read the line.
   941    char buf[kMaxLineSize] = {};
   942    ExpectReadable(replica_, kMaxLineSize, buf);
   943  
   944    ExpectFinished(replica_);
   945  }
   946  
   947  // Tests that data written in canonical mode can be read immediately once
   948  // switched to noncanonical mode.
   949  TEST_F(PtyTest, SwitchCanonToNoncanon) {
   950    // Write a few bytes without a terminating character, switch to noncanonical
   951    // mode, and read them.
   952    constexpr char kInput[] = "hello";
   953    ASSERT_THAT(WriteFd(master_.get(), kInput, sizeof(kInput)),
   954                SyscallSucceedsWithValue(sizeof(kInput)));
   955  
   956    // Nothing available yet.
   957    char buf[sizeof(kInput)] = {};
   958    ASSERT_THAT(PollAndReadFd(replica_.get(), buf, sizeof(kInput), kTimeout),
   959                PosixErrorIs(ETIMEDOUT, ::testing::StrEq("Poll timed out")));
   960  
   961    DisableCanonical();
   962  
   963    ExpectReadable(replica_, sizeof(kInput), buf);
   964    EXPECT_STREQ(buf, kInput);
   965  
   966    ExpectFinished(replica_);
   967  }
   968  
   969  TEST_F(PtyTest, SwitchCanonToNonCanonNewline) {
   970    // Write a few bytes with a terminating character.
   971    constexpr char kInput[] = "hello\n";
   972    ASSERT_THAT(WriteFd(master_.get(), kInput, sizeof(kInput)),
   973                SyscallSucceedsWithValue(sizeof(kInput)));
   974  
   975    DisableCanonical();
   976  
   977    // We can read the line.
   978    char buf[sizeof(kInput)] = {};
   979    ExpectReadable(replica_, sizeof(kInput), buf);
   980    EXPECT_STREQ(buf, kInput);
   981  
   982    ExpectFinished(replica_);
   983  }
   984  
   985  TEST_F(PtyTest, SwitchNoncanonToCanonNewlineBig) {
   986    DisableCanonical();
   987  
   988    // Write more than the maximum line size, then write a delimiter.
   989    constexpr int kWriteLen = 4100;
   990    char input[kWriteLen];
   991    memset(input, 'M', kWriteLen);
   992    ASSERT_THAT(WriteFd(master_.get(), input, kWriteLen),
   993                SyscallSucceedsWithValue(kWriteLen));
   994    // Wait for the input queue to fill.
   995    ASSERT_NO_ERRNO(WaitUntilReceived(replica_.get(), kMaxLineSize - 1));
   996    constexpr char delim = '\n';
   997    ASSERT_THAT(WriteFd(master_.get(), &delim, 1), SyscallSucceedsWithValue(1));
   998  
   999    EnableCanonical();
  1000  
  1001    // We can read the line.
  1002    char buf[kMaxLineSize] = {};
  1003    ExpectReadable(replica_, kMaxLineSize - 1, buf);
  1004  
  1005    // We can also read the remaining characters.
  1006    ExpectReadable(replica_, 6, buf);
  1007  
  1008    ExpectFinished(replica_);
  1009  }
  1010  
  1011  TEST_F(PtyTest, SwitchNoncanonToCanonNoNewline) {
  1012    DisableCanonical();
  1013  
  1014    // Write a few bytes without a terminating character.
  1015    // mode, and read them.
  1016    constexpr char kInput[] = "hello";
  1017    ASSERT_THAT(WriteFd(master_.get(), kInput, sizeof(kInput) - 1),
  1018                SyscallSucceedsWithValue(sizeof(kInput) - 1));
  1019  
  1020    ASSERT_NO_ERRNO(WaitUntilReceived(replica_.get(), sizeof(kInput) - 1));
  1021    EnableCanonical();
  1022  
  1023    // We can read the line.
  1024    char buf[sizeof(kInput)] = {};
  1025    ExpectReadable(replica_, sizeof(kInput) - 1, buf);
  1026    EXPECT_STREQ(buf, kInput);
  1027  
  1028    ExpectFinished(replica_);
  1029  }
  1030  
  1031  TEST_F(PtyTest, SwitchNoncanonToCanonNoNewlineBig) {
  1032    DisableCanonical();
  1033  
  1034    // Write a few bytes without a terminating character.
  1035    // mode, and read them.
  1036    constexpr int kWriteLen = 4100;
  1037    char input[kWriteLen];
  1038    memset(input, 'M', kWriteLen);
  1039    ASSERT_THAT(WriteFd(master_.get(), input, kWriteLen),
  1040                SyscallSucceedsWithValue(kWriteLen));
  1041  
  1042    ASSERT_NO_ERRNO(WaitUntilReceived(replica_.get(), kMaxLineSize - 1));
  1043    EnableCanonical();
  1044  
  1045    // We can read the line.
  1046    char buf[kMaxLineSize] = {};
  1047    ExpectReadable(replica_, kMaxLineSize - 1, buf);
  1048  
  1049    ExpectFinished(replica_);
  1050  }
  1051  
  1052  // Tests that we can write over the 4095 noncanonical limit, then read out
  1053  // everything.
  1054  TEST_F(PtyTest, NoncanonBigWrite) {
  1055    DisableCanonical();
  1056  
  1057    // Write well over the 4095 internal buffer limit.
  1058    constexpr char kInput = 'M';
  1059    constexpr int kInputSize = kMaxLineSize * 2;
  1060    for (int i = 0; i < kInputSize; i++) {
  1061      // This makes too many syscalls for save/restore.
  1062      const DisableSave ds;
  1063      ASSERT_THAT(WriteFd(master_.get(), &kInput, sizeof(kInput)),
  1064                  SyscallSucceedsWithValue(sizeof(kInput)));
  1065    }
  1066  
  1067    // We should be able to read out everything. Sleep a bit so that Linux has a
  1068    // chance to move data from the master to the replica.
  1069    ASSERT_NO_ERRNO(WaitUntilReceived(replica_.get(), kMaxLineSize - 1));
  1070    for (int i = 0; i < kInputSize; i++) {
  1071      // This makes too many syscalls for save/restore.
  1072      const DisableSave ds;
  1073      char c;
  1074      ExpectReadable(replica_, 1, &c);
  1075      ASSERT_EQ(c, kInput);
  1076    }
  1077  
  1078    ExpectFinished(replica_);
  1079  }
  1080  
  1081  // ICANON doesn't make input available until a line delimiter is typed.
  1082  //
  1083  // Test newline.
  1084  TEST_F(PtyTest, TermiosICANONNewline) {
  1085    char input[3] = {'a', 'b', 'c'};
  1086    ASSERT_THAT(WriteFd(master_.get(), input, sizeof(input)),
  1087                SyscallSucceedsWithValue(sizeof(input)));
  1088  
  1089    // Extra bytes for newline (written later) and NUL for EXPECT_STREQ.
  1090    char buf[5] = {};
  1091  
  1092    // Nothing available yet.
  1093    ASSERT_THAT(PollAndReadFd(replica_.get(), buf, sizeof(input), kTimeout),
  1094                PosixErrorIs(ETIMEDOUT, ::testing::StrEq("Poll timed out")));
  1095  
  1096    char delim = '\n';
  1097    ASSERT_THAT(WriteFd(master_.get(), &delim, 1), SyscallSucceedsWithValue(1));
  1098  
  1099    // Now it is available.
  1100    ASSERT_NO_ERRNO(WaitUntilReceived(replica_.get(), sizeof(input) + 1));
  1101    ExpectReadable(replica_, sizeof(input) + 1, buf);
  1102    EXPECT_STREQ(buf, "abc\n");
  1103  
  1104    ExpectFinished(replica_);
  1105  }
  1106  
  1107  // ICANON doesn't make input available until a line delimiter is typed.
  1108  //
  1109  // Test EOF (^D).
  1110  TEST_F(PtyTest, TermiosICANONEOF) {
  1111    char input[3] = {'a', 'b', 'c'};
  1112    ASSERT_THAT(WriteFd(master_.get(), input, sizeof(input)),
  1113                SyscallSucceedsWithValue(sizeof(input)));
  1114  
  1115    // Extra byte for NUL for EXPECT_STREQ.
  1116    char buf[4] = {};
  1117  
  1118    // Nothing available yet.
  1119    ASSERT_THAT(PollAndReadFd(replica_.get(), buf, sizeof(input), kTimeout),
  1120                PosixErrorIs(ETIMEDOUT, ::testing::StrEq("Poll timed out")));
  1121    char delim = ControlCharacter('D');
  1122    ASSERT_THAT(WriteFd(master_.get(), &delim, 1), SyscallSucceedsWithValue(1));
  1123  
  1124    // Now it is available. Note that ^D is not included.
  1125    ExpectReadable(replica_, sizeof(input), buf);
  1126    EXPECT_STREQ(buf, "abc");
  1127  
  1128    ExpectFinished(replica_);
  1129  }
  1130  
  1131  // ICANON limits us to 4096 bytes including a terminating character. Anything
  1132  // after and 4095th character is discarded (although still processed for
  1133  // signals and echoing).
  1134  TEST_F(PtyTest, CanonDiscard) {
  1135    constexpr char kInput = 'M';
  1136    constexpr int kInputSize = 4100;
  1137    constexpr int kIter = 3;
  1138  
  1139    // A few times write more than the 4096 character maximum, then a newline.
  1140    constexpr char delim = '\n';
  1141    for (int i = 0; i < kIter; i++) {
  1142      // This makes too many syscalls for save/restore.
  1143      const DisableSave ds;
  1144      for (int i = 0; i < kInputSize; i++) {
  1145        ASSERT_THAT(WriteFd(master_.get(), &kInput, sizeof(kInput)),
  1146                    SyscallSucceedsWithValue(sizeof(kInput)));
  1147      }
  1148      ASSERT_THAT(WriteFd(master_.get(), &delim, 1), SyscallSucceedsWithValue(1));
  1149    }
  1150  
  1151    // There should be multiple truncated lines available to read.
  1152    for (int i = 0; i < kIter; i++) {
  1153      char buf[kInputSize] = {};
  1154      ExpectReadable(replica_, kMaxLineSize, buf);
  1155      EXPECT_EQ(buf[kMaxLineSize - 1], delim);
  1156      EXPECT_EQ(buf[kMaxLineSize - 2], kInput);
  1157    }
  1158  
  1159    ExpectFinished(replica_);
  1160  }
  1161  
  1162  TEST_F(PtyTest, CanonMultiline) {
  1163    constexpr char kInput1[] = "GO\n";
  1164    constexpr char kInput2[] = "BLUE\n";
  1165  
  1166    // Write both lines.
  1167    ASSERT_THAT(WriteFd(master_.get(), kInput1, sizeof(kInput1) - 1),
  1168                SyscallSucceedsWithValue(sizeof(kInput1) - 1));
  1169    ASSERT_THAT(WriteFd(master_.get(), kInput2, sizeof(kInput2) - 1),
  1170                SyscallSucceedsWithValue(sizeof(kInput2) - 1));
  1171  
  1172    // Get the first line.
  1173    char line1[8] = {};
  1174    ExpectReadable(replica_, sizeof(kInput1) - 1, line1);
  1175    EXPECT_STREQ(line1, kInput1);
  1176  
  1177    // Get the second line.
  1178    char line2[8] = {};
  1179    ExpectReadable(replica_, sizeof(kInput2) - 1, line2);
  1180    EXPECT_STREQ(line2, kInput2);
  1181  
  1182    ExpectFinished(replica_);
  1183  }
  1184  
  1185  TEST_F(PtyTest, SwitchNoncanonToCanonMultiline) {
  1186    DisableCanonical();
  1187  
  1188    constexpr char kInput1[] = "GO\n";
  1189    constexpr char kInput2[] = "BLUE\n";
  1190    constexpr char kExpected[] = "GO\nBLUE\n";
  1191  
  1192    // Write both lines.
  1193    ASSERT_THAT(WriteFd(master_.get(), kInput1, sizeof(kInput1) - 1),
  1194                SyscallSucceedsWithValue(sizeof(kInput1) - 1));
  1195    ASSERT_THAT(WriteFd(master_.get(), kInput2, sizeof(kInput2) - 1),
  1196                SyscallSucceedsWithValue(sizeof(kInput2) - 1));
  1197  
  1198    ASSERT_NO_ERRNO(
  1199        WaitUntilReceived(replica_.get(), sizeof(kInput1) + sizeof(kInput2) - 2));
  1200    EnableCanonical();
  1201  
  1202    // Get all together as one line.
  1203    char line[9] = {};
  1204    ExpectReadable(replica_, 8, line);
  1205    EXPECT_STREQ(line, kExpected);
  1206  
  1207    ExpectFinished(replica_);
  1208  }
  1209  
  1210  TEST_F(PtyTest, SwitchTwiceMultiline) {
  1211    std::string kInputs[] = {"GO\n", "BLUE\n", "!"};
  1212    std::string kExpected = "GO\nBLUE\n!";
  1213  
  1214    // Write each line.
  1215    for (const std::string& input : kInputs) {
  1216      ASSERT_THAT(WriteFd(master_.get(), input.c_str(), input.size()),
  1217                  SyscallSucceedsWithValue(input.size()));
  1218    }
  1219  
  1220    DisableCanonical();
  1221    // All written characters have to make it into the input queue before
  1222    // canonical mode is re-enabled. If the final '!' character hasn't been
  1223    // enqueued before canonical mode is re-enabled, it won't be readable.
  1224    ASSERT_NO_ERRNO(WaitUntilReceived(replica_.get(), kExpected.size()));
  1225    EnableCanonical();
  1226  
  1227    // Get all together as one line.
  1228    char line[10] = {};
  1229    ExpectReadable(replica_, 9, line);
  1230    EXPECT_STREQ(line, kExpected.c_str());
  1231  
  1232    ExpectFinished(replica_);
  1233  }
  1234  
  1235  TEST_F(PtyTest, QueueSize) {
  1236    // Write the line.
  1237    constexpr char kInput1[] = "GO\n";
  1238    ASSERT_THAT(WriteFd(master_.get(), kInput1, sizeof(kInput1) - 1),
  1239                SyscallSucceedsWithValue(sizeof(kInput1) - 1));
  1240    ASSERT_NO_ERRNO(WaitUntilReceived(replica_.get(), sizeof(kInput1) - 1));
  1241  
  1242    // Ensure that writing more (beyond what is readable) does not impact the
  1243    // readable size.
  1244    char input[kMaxLineSize];
  1245    memset(input, 'M', kMaxLineSize);
  1246    ASSERT_THAT(WriteFd(master_.get(), input, kMaxLineSize),
  1247                SyscallSucceedsWithValue(kMaxLineSize));
  1248    int inputBufSize = ASSERT_NO_ERRNO_AND_VALUE(
  1249        WaitUntilReceived(replica_.get(), sizeof(kInput1) - 1));
  1250    EXPECT_EQ(inputBufSize, sizeof(kInput1) - 1);
  1251  }
  1252  
  1253  TEST_F(PtyTest, PartialBadBuffer) {
  1254    // Allocate 2 pages.
  1255    void* addr = mmap(nullptr, 2 * kPageSize, PROT_READ | PROT_WRITE,
  1256                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  1257    ASSERT_NE(addr, MAP_FAILED);
  1258    char* buf = reinterpret_cast<char*>(addr);
  1259  
  1260    // Guard the 2nd page for our read to run into.
  1261    ASSERT_THAT(
  1262        mprotect(reinterpret_cast<void*>(buf + kPageSize), kPageSize, PROT_NONE),
  1263        SyscallSucceeds());
  1264  
  1265    // Leave only one free byte in the buffer.
  1266    char* bad_buffer = buf + kPageSize - 1;
  1267  
  1268    // Write to the master.
  1269    constexpr char kBuf[] = "hello\n";
  1270    constexpr size_t size = sizeof(kBuf) - 1;
  1271    EXPECT_THAT(WriteFd(master_.get(), kBuf, size),
  1272                SyscallSucceedsWithValue(size));
  1273  
  1274    // Read from the replica into bad_buffer.
  1275    ASSERT_NO_ERRNO(WaitUntilReceived(replica_.get(), size));
  1276    // Before Linux 3b830a9c this returned EFAULT, but after that commit it
  1277    // returns EAGAIN.
  1278    EXPECT_THAT(
  1279        ReadFd(replica_.get(), bad_buffer, size),
  1280        AnyOf(SyscallFailsWithErrno(EFAULT), SyscallFailsWithErrno(EAGAIN)));
  1281  
  1282    EXPECT_THAT(munmap(addr, 2 * kPageSize), SyscallSucceeds()) << addr;
  1283  }
  1284  
  1285  TEST_F(PtyTest, SimpleEcho) {
  1286    constexpr char kInput[] = "Mr. Eko";
  1287    EXPECT_THAT(WriteFd(master_.get(), kInput, strlen(kInput)),
  1288                SyscallSucceedsWithValue(strlen(kInput)));
  1289  
  1290    char buf[100] = {};
  1291    ExpectReadable(master_, strlen(kInput), buf);
  1292  
  1293    EXPECT_STREQ(buf, kInput);
  1294    ExpectFinished(master_);
  1295  }
  1296  
  1297  TEST_F(PtyTest, GetWindowSize) {
  1298    struct winsize ws;
  1299    ASSERT_THAT(ioctl(replica_.get(), TIOCGWINSZ, &ws), SyscallSucceeds());
  1300    EXPECT_EQ(ws.ws_row, 0);
  1301    EXPECT_EQ(ws.ws_col, 0);
  1302  }
  1303  
  1304  TEST_F(PtyTest, SetReplicaWindowSize) {
  1305    constexpr uint16_t kRows = 343;
  1306    constexpr uint16_t kCols = 2401;
  1307    struct winsize ws = {.ws_row = kRows, .ws_col = kCols};
  1308    ASSERT_THAT(ioctl(replica_.get(), TIOCSWINSZ, &ws), SyscallSucceeds());
  1309  
  1310    struct winsize retrieved_ws = {};
  1311    ASSERT_THAT(ioctl(master_.get(), TIOCGWINSZ, &retrieved_ws),
  1312                SyscallSucceeds());
  1313    EXPECT_EQ(retrieved_ws.ws_row, kRows);
  1314    EXPECT_EQ(retrieved_ws.ws_col, kCols);
  1315  }
  1316  
  1317  TEST_F(PtyTest, SetMasterWindowSize) {
  1318    constexpr uint16_t kRows = 343;
  1319    constexpr uint16_t kCols = 2401;
  1320    struct winsize ws = {.ws_row = kRows, .ws_col = kCols};
  1321    ASSERT_THAT(ioctl(master_.get(), TIOCSWINSZ, &ws), SyscallSucceeds());
  1322  
  1323    struct winsize retrieved_ws = {};
  1324    ASSERT_THAT(ioctl(replica_.get(), TIOCGWINSZ, &retrieved_ws),
  1325                SyscallSucceeds());
  1326    EXPECT_EQ(retrieved_ws.ws_row, kRows);
  1327    EXPECT_EQ(retrieved_ws.ws_col, kCols);
  1328  }
  1329  
  1330  class JobControlTest : public ::testing::Test {
  1331   protected:
  1332    void SetUp() override {
  1333      master_ = ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/ptmx", O_RDWR | O_NONBLOCK));
  1334      replica_ = ASSERT_NO_ERRNO_AND_VALUE(OpenReplica(master_));
  1335  
  1336      // Make this a session leader, which also drops the controlling terminal.
  1337      // In the gVisor test environment, this test will be run as the session
  1338      // leader already (as the sentry init process).
  1339      if (!IsRunningOnGvisor()) {
  1340        // Ignore failure because setsid(2) fails if the process is already the
  1341        // session leader.
  1342        setsid();
  1343        ioctl(replica_.get(), TIOCNOTTY);
  1344      }
  1345    }
  1346  
  1347    PosixError RunInChild(SubprocessCallback childFunc) {
  1348      pid_t child = fork();
  1349      if (!child) {
  1350        childFunc();
  1351        _exit(0);
  1352      }
  1353      int wstatus;
  1354      if (waitpid(child, &wstatus, 0) != child) {
  1355        return PosixError(
  1356            errno, absl::StrCat("child failed with wait status: ", wstatus));
  1357      }
  1358      return PosixError(wstatus, "process returned");
  1359    }
  1360  
  1361    // Master and replica ends of the PTY. Non-blocking.
  1362    FileDescriptor master_;
  1363    FileDescriptor replica_;
  1364  };
  1365  
  1366  TEST_F(JobControlTest, SetTTYMaster) {
  1367    auto res = RunInChild([=]() {
  1368      TEST_PCHECK(setsid() >= 0);
  1369      TEST_PCHECK(!ioctl(master_.get(), TIOCSCTTY, 0));
  1370    });
  1371    ASSERT_NO_ERRNO(res);
  1372  }
  1373  
  1374  TEST_F(JobControlTest, SetTTY) {
  1375    auto res = RunInChild([=]() {
  1376      TEST_PCHECK(setsid() >= 0);
  1377      TEST_PCHECK(ioctl(!replica_.get(), TIOCSCTTY, 0));
  1378    });
  1379    ASSERT_NO_ERRNO(res);
  1380  }
  1381  
  1382  TEST_F(JobControlTest, SetTTYNonLeader) {
  1383    // Fork a process that won't be the session leader.
  1384    auto res =
  1385        RunInChild([=]() { TEST_PCHECK(ioctl(replica_.get(), TIOCSCTTY, 0)); });
  1386    ASSERT_NO_ERRNO(res);
  1387  }
  1388  
  1389  TEST_F(JobControlTest, SetTTYBadArg) {
  1390    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1391    auto res = RunInChild([=]() {
  1392      TEST_PCHECK(setsid() >= 0);
  1393      TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 1));
  1394    });
  1395    ASSERT_NO_ERRNO(res);
  1396  }
  1397  
  1398  TEST_F(JobControlTest, SetTTYDifferentSession) {
  1399    SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1400  
  1401    auto res = RunInChild([=]() {
  1402      TEST_PCHECK(setsid() >= 0);
  1403      TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 1));
  1404  
  1405      // Fork, join a new session, and try to steal the parent's controlling
  1406      // terminal, which should fail.
  1407      pid_t grandchild = fork();
  1408      if (!grandchild) {
  1409        TEST_PCHECK(setsid() >= 0);
  1410        // We shouldn't be able to steal the terminal.
  1411        TEST_PCHECK(ioctl(replica_.get(), TIOCSCTTY, 1));
  1412        _exit(0);
  1413      }
  1414  
  1415      int gcwstatus;
  1416      TEST_PCHECK(waitpid(grandchild, &gcwstatus, 0) == grandchild);
  1417      TEST_PCHECK(gcwstatus == 0);
  1418    });
  1419    ASSERT_NO_ERRNO(res);
  1420  }
  1421  
  1422  TEST_F(JobControlTest, ReleaseTTY) {
  1423    ASSERT_THAT(ioctl(replica_.get(), TIOCSCTTY, 0), SyscallSucceeds());
  1424  
  1425    // Make sure we're ignoring SIGHUP, which will be sent to this process once we
  1426    // disconnect the TTY.
  1427    struct sigaction sa = {};
  1428    sa.sa_handler = SIG_IGN;
  1429    sa.sa_flags = 0;
  1430    sigemptyset(&sa.sa_mask);
  1431    struct sigaction old_sa;
  1432    EXPECT_THAT(sigaction(SIGHUP, &sa, &old_sa), SyscallSucceeds());
  1433    EXPECT_THAT(ioctl(replica_.get(), TIOCNOTTY), SyscallSucceeds());
  1434    EXPECT_THAT(sigaction(SIGHUP, &old_sa, NULL), SyscallSucceeds());
  1435  }
  1436  
  1437  TEST_F(JobControlTest, ReleaseUnsetTTY) {
  1438    ASSERT_THAT(ioctl(replica_.get(), TIOCNOTTY), SyscallFailsWithErrno(ENOTTY));
  1439  }
  1440  
  1441  TEST_F(JobControlTest, ReleaseWrongTTY) {
  1442    auto res = RunInChild([=]() {
  1443      TEST_PCHECK(setsid() >= 0);
  1444      TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 0));
  1445      TEST_PCHECK(ioctl(master_.get(), TIOCNOTTY) < 0 && errno == ENOTTY);
  1446    });
  1447    ASSERT_NO_ERRNO(res);
  1448  }
  1449  
  1450  TEST_F(JobControlTest, ReleaseTTYNonLeader) {
  1451    auto ret = RunInChild([=]() {
  1452      TEST_PCHECK(setsid() >= 0);
  1453      TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 0));
  1454  
  1455      pid_t grandchild = fork();
  1456      if (!grandchild) {
  1457        TEST_PCHECK(!ioctl(replica_.get(), TIOCNOTTY));
  1458        _exit(0);
  1459      }
  1460  
  1461      int wstatus;
  1462      TEST_PCHECK(waitpid(grandchild, &wstatus, 0) == grandchild);
  1463      TEST_PCHECK(wstatus == 0);
  1464    });
  1465    ASSERT_NO_ERRNO(ret);
  1466  }
  1467  
  1468  TEST_F(JobControlTest, ReleaseTTYDifferentSession) {
  1469    auto ret = RunInChild([=]() {
  1470      TEST_PCHECK(setsid() >= 0);
  1471  
  1472      TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 0));
  1473  
  1474      pid_t grandchild = fork();
  1475      if (!grandchild) {
  1476        // Join a new session, then try to disconnect.
  1477        TEST_PCHECK(setsid() >= 0);
  1478        TEST_PCHECK(ioctl(replica_.get(), TIOCNOTTY));
  1479        _exit(0);
  1480      }
  1481  
  1482      int wstatus;
  1483      TEST_PCHECK(waitpid(grandchild, &wstatus, 0) == grandchild);
  1484      TEST_PCHECK(wstatus == 0);
  1485    });
  1486    ASSERT_NO_ERRNO(ret);
  1487  }
  1488  
  1489  // Used by the child process spawned in ReleaseTTYSignals to track received
  1490  // signals.
  1491  static int received;
  1492  
  1493  void sig_handler(int signum) { received |= signum; }
  1494  
  1495  // When the session leader releases its controlling terminal, the foreground
  1496  // process group gets SIGHUP, then SIGCONT. This test:
  1497  // - Spawns 2 threads
  1498  // - Has thread 1 return 0 if it gets both SIGHUP and SIGCONT
  1499  // - Has thread 2 leave the foreground process group, and return non-zero if it
  1500  //   receives any signals.
  1501  // - Has the parent thread release its controlling terminal
  1502  // - Checks that thread 1 got both signals
  1503  // - Checks that thread 2 didn't get any signals.
  1504  TEST_F(JobControlTest, ReleaseTTYSignals) {
  1505    ASSERT_THAT(ioctl(replica_.get(), TIOCSCTTY, 0), SyscallSucceeds());
  1506  
  1507    received = 0;
  1508    struct sigaction sa = {};
  1509    sa.sa_handler = sig_handler;
  1510    sa.sa_flags = 0;
  1511    sigemptyset(&sa.sa_mask);
  1512    sigaddset(&sa.sa_mask, SIGHUP);
  1513    sigaddset(&sa.sa_mask, SIGCONT);
  1514    sigprocmask(SIG_BLOCK, &sa.sa_mask, NULL);
  1515  
  1516    pid_t same_pgrp_child = fork();
  1517    if (!same_pgrp_child) {
  1518      // The child will wait for SIGHUP and SIGCONT, then return 0. It begins with
  1519      // SIGHUP and SIGCONT blocked. We install signal handlers for those signals,
  1520      // then use sigsuspend to wait for those specific signals.
  1521      TEST_PCHECK(!sigaction(SIGHUP, &sa, NULL));
  1522      TEST_PCHECK(!sigaction(SIGCONT, &sa, NULL));
  1523      sigset_t mask;
  1524      sigfillset(&mask);
  1525      sigdelset(&mask, SIGHUP);
  1526      sigdelset(&mask, SIGCONT);
  1527      while (received != (SIGHUP | SIGCONT)) {
  1528        sigsuspend(&mask);
  1529      }
  1530      _exit(0);
  1531    }
  1532  
  1533    // We don't want to block these anymore.
  1534    sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL);
  1535  
  1536    // This child will return non-zero if either SIGHUP or SIGCONT are received.
  1537    pid_t diff_pgrp_child = fork();
  1538    if (!diff_pgrp_child) {
  1539      TEST_PCHECK(!setpgid(0, 0));
  1540      TEST_PCHECK(pause());
  1541      _exit(1);
  1542    }
  1543  
  1544    EXPECT_THAT(setpgid(diff_pgrp_child, diff_pgrp_child), SyscallSucceeds());
  1545  
  1546    // Make sure we're ignoring SIGHUP, which will be sent to this process once we
  1547    // disconnect the TTY.
  1548    struct sigaction sighup_sa = {};
  1549    sighup_sa.sa_handler = SIG_IGN;
  1550    sighup_sa.sa_flags = 0;
  1551    sigemptyset(&sighup_sa.sa_mask);
  1552    struct sigaction old_sa;
  1553    EXPECT_THAT(sigaction(SIGHUP, &sighup_sa, &old_sa), SyscallSucceeds());
  1554  
  1555    // Release the controlling terminal, sending SIGHUP and SIGCONT to all other
  1556    // processes in this process group.
  1557    EXPECT_THAT(ioctl(replica_.get(), TIOCNOTTY), SyscallSucceeds());
  1558  
  1559    EXPECT_THAT(sigaction(SIGHUP, &old_sa, NULL), SyscallSucceeds());
  1560  
  1561    // The child in the same process group will get signaled.
  1562    int wstatus;
  1563    EXPECT_THAT(waitpid(same_pgrp_child, &wstatus, 0),
  1564                SyscallSucceedsWithValue(same_pgrp_child));
  1565    EXPECT_EQ(wstatus, 0);
  1566  
  1567    // The other child will not get signaled.
  1568    EXPECT_THAT(waitpid(diff_pgrp_child, &wstatus, WNOHANG),
  1569                SyscallSucceedsWithValue(0));
  1570    EXPECT_THAT(kill(diff_pgrp_child, SIGKILL), SyscallSucceeds());
  1571  }
  1572  
  1573  TEST_F(JobControlTest, GetForegroundProcessGroup) {
  1574    auto res = RunInChild([=]() {
  1575      pid_t pid, foreground_pgid;
  1576      TEST_PCHECK(setsid() >= 0);
  1577      TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 1));
  1578      TEST_PCHECK(!ioctl(replica_.get(), TIOCGPGRP, &foreground_pgid));
  1579      TEST_PCHECK((pid = getpid()) >= 0);
  1580      TEST_PCHECK(pid == foreground_pgid);
  1581    });
  1582    ASSERT_NO_ERRNO(res);
  1583  }
  1584  
  1585  TEST_F(JobControlTest, GetForegroundProcessGroupNonControlling) {
  1586    // At this point there's no controlling terminal, so TIOCGPGRP should fail.
  1587    pid_t foreground_pgid;
  1588    ASSERT_THAT(ioctl(replica_.get(), TIOCGPGRP, &foreground_pgid),
  1589                SyscallFailsWithErrno(ENOTTY));
  1590  }
  1591  
  1592  // This test:
  1593  // - sets itself as the foreground process group
  1594  // - creates a child process in a new process group
  1595  // - sets that child as the foreground process group
  1596  // - kills its child and sets itself as the foreground process group.
  1597  // TODO(gvisor.dev/issue/5357): Fix and enable.
  1598  TEST_F(JobControlTest, DISABLED_SetForegroundProcessGroup) {
  1599    auto res = RunInChild([=]() {
  1600      TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 0));
  1601  
  1602      // Ignore SIGTTOU so that we don't stop ourself when calling tcsetpgrp.
  1603      struct sigaction sa = {};
  1604      sa.sa_handler = SIG_IGN;
  1605      sa.sa_flags = 0;
  1606      sigemptyset(&sa.sa_mask);
  1607      sigaction(SIGTTOU, &sa, NULL);
  1608  
  1609      // Set ourself as the foreground process group.
  1610      TEST_PCHECK(!tcsetpgrp(replica_.get(), getpgid(0)));
  1611  
  1612      // Create a new process that just waits to be signaled.
  1613      pid_t grandchild = fork();
  1614      if (!grandchild) {
  1615        TEST_PCHECK(!pause());
  1616        // We should never reach this.
  1617        _exit(1);
  1618      }
  1619  
  1620      // Make the child its own process group, then make it the controlling
  1621      // process group of the terminal.
  1622      TEST_PCHECK(!setpgid(grandchild, grandchild));
  1623      TEST_PCHECK(!tcsetpgrp(replica_.get(), grandchild));
  1624  
  1625      // Sanity check - we're still the controlling session.
  1626      TEST_PCHECK(getsid(0) == getsid(grandchild));
  1627  
  1628      // Signal the child, wait for it to exit, then retake the terminal.
  1629      TEST_PCHECK(!kill(grandchild, SIGTERM));
  1630      int wstatus;
  1631      TEST_PCHECK(waitpid(grandchild, &wstatus, 0) == grandchild);
  1632      TEST_PCHECK(WIFSIGNALED(wstatus));
  1633      TEST_PCHECK(WTERMSIG(wstatus) == SIGTERM);
  1634  
  1635      // Set ourself as the foreground process.
  1636      pid_t pgid;
  1637      TEST_PCHECK(pgid = getpgid(0) == 0);
  1638      TEST_PCHECK(!tcsetpgrp(replica_.get(), pgid));
  1639    });
  1640    ASSERT_NO_ERRNO(res);
  1641  }
  1642  
  1643  TEST_F(JobControlTest, SetForegroundProcessGroupWrongTTY) {
  1644    pid_t pid = getpid();
  1645    ASSERT_THAT(ioctl(replica_.get(), TIOCSPGRP, &pid),
  1646                SyscallFailsWithErrno(ENOTTY));
  1647  }
  1648  
  1649  TEST_F(JobControlTest, SetForegroundProcessGroupNegPgid) {
  1650    auto ret = RunInChild([=]() {
  1651      TEST_PCHECK(setsid() >= 0);
  1652      TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 0));
  1653  
  1654      pid_t pid = -1;
  1655      TEST_PCHECK(ioctl(replica_.get(), TIOCSPGRP, &pid) && errno == EINVAL);
  1656    });
  1657    ASSERT_NO_ERRNO(ret);
  1658  }
  1659  
  1660  // TODO(gvisor.dev/issue/5357): Fix and enable.
  1661  TEST_F(JobControlTest, DISABLED_SetForegroundProcessGroupEmptyProcessGroup) {
  1662    auto res = RunInChild([=]() {
  1663      TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 0));
  1664  
  1665      // Create a new process, put it in a new process group, make that group the
  1666      // foreground process group, then have the process wait.
  1667      pid_t grandchild = fork();
  1668      if (!grandchild) {
  1669        TEST_PCHECK(!setpgid(0, 0));
  1670        _exit(0);
  1671      }
  1672  
  1673      // Wait for the child to exit.
  1674      int wstatus;
  1675      TEST_PCHECK(waitpid(grandchild, &wstatus, 0) == grandchild);
  1676      // The child's process group doesn't exist anymore - this should fail.
  1677      TEST_PCHECK(ioctl(replica_.get(), TIOCSPGRP, &grandchild) != 0 &&
  1678                  errno == ESRCH);
  1679    });
  1680    ASSERT_NO_ERRNO(res);
  1681  }
  1682  
  1683  TEST_F(JobControlTest, SetForegroundProcessGroupDifferentSession) {
  1684    auto ret = RunInChild([=]() {
  1685      TEST_PCHECK(setsid() >= 0);
  1686      TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 0));
  1687  
  1688      int sync_setsid[2];
  1689      int sync_exit[2];
  1690      TEST_PCHECK(pipe(sync_setsid) >= 0);
  1691      TEST_PCHECK(pipe(sync_exit) >= 0);
  1692  
  1693      // Create a new process and put it in a new session.
  1694      pid_t grandchild = fork();
  1695      if (!grandchild) {
  1696        TEST_PCHECK(setsid() >= 0);
  1697        // Tell the parent we're in a new session.
  1698        char c = 'c';
  1699        TEST_PCHECK(WriteFd(sync_setsid[1], &c, 1) == 1);
  1700        TEST_PCHECK(ReadFd(sync_exit[0], &c, 1) == 1);
  1701        _exit(0);
  1702      }
  1703  
  1704      // Wait for the child to tell us it's in a new session.
  1705      char c = 'c';
  1706      TEST_PCHECK(ReadFd(sync_setsid[0], &c, 1) == 1);
  1707  
  1708      // Child is in a new session, so we can't make it the foregroup process
  1709      // group.
  1710      TEST_PCHECK(ioctl(replica_.get(), TIOCSPGRP, &grandchild) &&
  1711                  errno == EPERM);
  1712  
  1713      TEST_PCHECK(WriteFd(sync_exit[1], &c, 1) == 1);
  1714  
  1715      int wstatus;
  1716      TEST_PCHECK(waitpid(grandchild, &wstatus, 0) == grandchild);
  1717      TEST_PCHECK(WIFEXITED(wstatus));
  1718      TEST_PCHECK(!WEXITSTATUS(wstatus));
  1719    });
  1720    ASSERT_NO_ERRNO(ret);
  1721  }
  1722  
  1723  // Verify that we don't hang when creating a new session from an orphaned
  1724  // process group (b/139968068). Calling setsid() creates an orphaned process
  1725  // group, as process groups that contain the session's leading process are
  1726  // orphans.
  1727  //
  1728  // We create 2 sessions in this test. The init process in gVisor is considered
  1729  // not to be an orphan (see sessions.go), so we have to create a session from
  1730  // which to create a session. The latter session is being created from an
  1731  // orphaned process group.
  1732  TEST_F(JobControlTest, OrphanRegression) {
  1733    pid_t session_2_leader = fork();
  1734    if (!session_2_leader) {
  1735      TEST_PCHECK(setsid() >= 0);
  1736  
  1737      pid_t session_3_leader = fork();
  1738      if (!session_3_leader) {
  1739        TEST_PCHECK(setsid() >= 0);
  1740  
  1741        _exit(0);
  1742      }
  1743  
  1744      int wstatus;
  1745      TEST_PCHECK(waitpid(session_3_leader, &wstatus, 0) == session_3_leader);
  1746      TEST_PCHECK(wstatus == 0);
  1747  
  1748      _exit(0);
  1749    }
  1750  
  1751    int wstatus;
  1752    ASSERT_THAT(waitpid(session_2_leader, &wstatus, 0),
  1753                SyscallSucceedsWithValue(session_2_leader));
  1754    ASSERT_EQ(wstatus, 0);
  1755  }
  1756  
  1757  }  // namespace
  1758  }  // namespace testing
  1759  }  // namespace gvisor