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, ¬ify]() { 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, ¬ify]() { 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