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