gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/ptrace.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 <elf.h> 16 #include <signal.h> 17 #include <stddef.h> 18 #include <sys/prctl.h> 19 #include <sys/ptrace.h> 20 #include <sys/socket.h> 21 #include <sys/time.h> 22 #include <sys/types.h> 23 #include <sys/user.h> 24 #include <sys/wait.h> 25 #include <unistd.h> 26 27 #include <iostream> 28 #include <utility> 29 30 #include "gmock/gmock.h" 31 #include "gtest/gtest.h" 32 #include "absl/flags/flag.h" 33 #include "absl/strings/string_view.h" 34 #include "absl/time/clock.h" 35 #include "absl/time/time.h" 36 #include "test/util/capability_util.h" 37 #include "test/util/fs_util.h" 38 #include "test/util/logging.h" 39 #include "test/util/memory_util.h" 40 #include "test/util/multiprocess_util.h" 41 #include "test/util/platform_util.h" 42 #include "test/util/signal_util.h" 43 #include "test/util/temp_path.h" 44 #include "test/util/test_util.h" 45 #include "test/util/thread_util.h" 46 #include "test/util/time_util.h" 47 48 ABSL_FLAG(bool, ptrace_test_execve_child, false, 49 "If true, run the " 50 "PtraceExecveTest_Execve_GetRegs_PeekUser_SIGKILL_TraceClone_" 51 "TraceExit child workload."); 52 ABSL_FLAG(bool, ptrace_test_trace_descendants_allowed, false, 53 "If set, run the child workload for " 54 "PtraceTest_TraceDescendantsAllowed."); 55 ABSL_FLAG(bool, ptrace_test_ptrace_attacher, false, 56 "If set, run the child workload for PtraceAttacherSubprocess."); 57 ABSL_FLAG(bool, ptrace_test_prctl_set_ptracer, false, 58 "If set, run the child workload for PrctlSetPtracerSubprocess."); 59 ABSL_FLAG(bool, ptrace_test_prctl_set_ptracer_and_exit_tracee_thread, false, 60 "If set, run the child workload for " 61 "PtraceTest_PrctlSetPtracerPersistsPastTraceeThreadExit."); 62 ABSL_FLAG(bool, ptrace_test_prctl_set_ptracer_and_exec_non_leader, false, 63 "If set, run the child workload for " 64 "PtraceTest_PrctlSetPtracerDoesNotPersistPastNonLeaderExec."); 65 ABSL_FLAG(bool, ptrace_test_prctl_set_ptracer_and_exit_tracer_thread, false, 66 "If set, run the child workload for " 67 "PtraceTest_PrctlSetPtracerDoesNotPersistPastTracerThreadExit."); 68 ABSL_FLAG(int, ptrace_test_prctl_set_ptracer_and_exit_tracer_thread_tid, -1, 69 "Specifies the tracee tid in the child workload for " 70 "PtraceTest_PrctlSetPtracerDoesNotPersistPastTracerThreadExit."); 71 ABSL_FLAG(bool, ptrace_test_prctl_set_ptracer_respects_tracer_thread_id, false, 72 "If set, run the child workload for PtraceTest_PrctlSetPtracePID."); 73 ABSL_FLAG(int, ptrace_test_prctl_set_ptracer_respects_tracer_thread_id_tid, -1, 74 "Specifies the thread tid to be traced in the child workload " 75 "for PtraceTest_PrctlSetPtracerRespectsTracerThreadID."); 76 77 ABSL_FLAG(bool, ptrace_test_tracee, false, 78 "If true, run the tracee process for the " 79 "PrctlSetPtracerDoesNotPersistPastLeaderExec and " 80 "PrctlSetPtracerDoesNotPersistPastNonLeaderExec workloads."); 81 ABSL_FLAG(int, ptrace_test_trace_tid, -1, 82 "If set, run a process to ptrace attach to the thread with the " 83 "specified pid for the PrctlSetPtracerRespectsTracerThreadID " 84 "workload."); 85 ABSL_FLAG(int, ptrace_test_fd, -1, 86 "Specifies the fd used for communication between tracer and tracee " 87 "processes across exec."); 88 89 namespace gvisor { 90 namespace testing { 91 92 namespace { 93 94 // PTRACE_GETSIGMASK and PTRACE_SETSIGMASK are not defined until glibc 2.23 95 // (fb53a27c5741 "Add new header definitions from Linux 4.4 (plus older ptrace 96 // definitions)"). 97 constexpr auto kPtraceGetSigMask = static_cast<__ptrace_request>(0x420a); 98 constexpr auto kPtraceSetSigMask = static_cast<__ptrace_request>(0x420b); 99 100 // PTRACE_SYSEMU is not defined until glibc 2.27 (c48831d0eebf "linux/x86: sync 101 // sys/ptrace.h with Linux 4.14 [BZ #22433]"). 102 constexpr auto kPtraceSysemu = static_cast<__ptrace_request>(31); 103 104 // PTRACE_EVENT_STOP is not defined until glibc 2.26 (3f67d1a7021e "Add Linux 105 // PTRACE_EVENT_STOP"). 106 constexpr int kPtraceEventStop = 128; 107 108 // Sends sig to the current process with tgkill(2). 109 // 110 // glibc's raise(2) may change the signal mask before sending the signal. These 111 // extra syscalls make tests of syscall, signal interception, etc. difficult to 112 // write. 113 void RaiseSignal(int sig) { 114 pid_t pid = getpid(); 115 TEST_PCHECK(pid > 0); 116 pid_t tid = gettid(); 117 TEST_PCHECK(tid > 0); 118 TEST_PCHECK(tgkill(pid, tid, sig) == 0); 119 } 120 121 constexpr char kYamaPtraceScopePath[] = "/proc/sys/kernel/yama/ptrace_scope"; 122 123 // Returns the Yama ptrace scope. 124 PosixErrorOr<int> YamaPtraceScope() { 125 ASSIGN_OR_RETURN_ERRNO(bool exists, Exists(kYamaPtraceScopePath)); 126 if (!exists) { 127 // File doesn't exist means no Yama, so the scope is disabled -> 0. 128 return 0; 129 } 130 131 std::string contents; 132 RETURN_IF_ERRNO(GetContents(kYamaPtraceScopePath, &contents)); 133 134 int scope; 135 if (!absl::SimpleAtoi(contents, &scope)) { 136 return PosixError(EINVAL, absl::StrCat(contents, ": not a valid number")); 137 } 138 139 return scope; 140 } 141 142 int CheckPtraceAttach(pid_t pid) { 143 int ret = ptrace(PTRACE_ATTACH, pid, 0, 0); 144 MaybeSave(); 145 if (ret < 0) { 146 return ret; 147 } 148 149 int status; 150 TEST_PCHECK(waitpid(pid, &status, 0) == pid); 151 MaybeSave(); 152 TEST_CHECK(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP); 153 TEST_PCHECK(ptrace(PTRACE_DETACH, pid, 0, 0) == 0); 154 MaybeSave(); 155 return 0; 156 } 157 158 class SimpleSubprocess { 159 public: 160 explicit SimpleSubprocess(absl::string_view child_flag) { 161 int sockets[2]; 162 TEST_PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == 0); 163 164 // Allocate vector before forking (not async-signal-safe). 165 ExecveArray const owned_child_argv = {"/proc/self/exe", child_flag, 166 "--ptrace_test_fd", 167 std::to_string(sockets[0])}; 168 char* const* const child_argv = owned_child_argv.get(); 169 170 pid_ = fork(); 171 if (pid_ == 0) { 172 TEST_PCHECK(close(sockets[1]) == 0); 173 execve(child_argv[0], child_argv, /* envp = */ nullptr); 174 TEST_PCHECK_MSG(false, "Survived execve to test child"); 175 } 176 TEST_PCHECK(pid_ > 0); 177 TEST_PCHECK(close(sockets[0]) == 0); 178 sockfd_ = sockets[1]; 179 } 180 181 SimpleSubprocess(SimpleSubprocess&& orig) 182 : pid_(orig.pid_), sockfd_(orig.sockfd_) { 183 orig.pid_ = -1; 184 orig.sockfd_ = -1; 185 } 186 187 SimpleSubprocess& operator=(SimpleSubprocess&& orig) { 188 if (this != &orig) { 189 this->~SimpleSubprocess(); 190 pid_ = orig.pid_; 191 sockfd_ = orig.sockfd_; 192 orig.pid_ = -1; 193 orig.sockfd_ = -1; 194 } 195 return *this; 196 } 197 198 SimpleSubprocess(SimpleSubprocess const&) = delete; 199 SimpleSubprocess& operator=(SimpleSubprocess const&) = delete; 200 201 ~SimpleSubprocess() { 202 if (pid_ < 0) { 203 return; 204 } 205 EXPECT_THAT(shutdown(sockfd_, SHUT_RDWR), SyscallSucceeds()); 206 EXPECT_THAT(close(sockfd_), SyscallSucceeds()); 207 int status; 208 EXPECT_THAT(waitpid(pid_, &status, 0), SyscallSucceedsWithValue(pid_)); 209 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 210 << " status " << status; 211 } 212 213 pid_t pid() const { return pid_; } 214 215 // Sends the child process the given value, receives an errno in response, and 216 // returns a PosixError corresponding to the received errno. 217 template <typename T> 218 PosixError Cmd(T val) { 219 if (WriteFd(sockfd_, &val, sizeof(val)) < 0) { 220 return PosixError(errno, "write failed"); 221 } 222 return RecvErrno(); 223 } 224 225 private: 226 PosixError RecvErrno() { 227 int resp_errno; 228 if (ReadFd(sockfd_, &resp_errno, sizeof(resp_errno)) < 0) { 229 return PosixError(errno, "read failed"); 230 } 231 return PosixError(resp_errno); 232 } 233 234 pid_t pid_ = -1; 235 int sockfd_ = -1; 236 }; 237 238 TEST(PtraceTest, AttachSelf) { 239 EXPECT_THAT(ptrace(PTRACE_ATTACH, gettid(), 0, 0), 240 SyscallFailsWithErrno(EPERM)); 241 } 242 243 TEST(PtraceTest, AttachSameThreadGroup) { 244 pid_t const tid = gettid(); 245 ScopedThread([&] { 246 EXPECT_THAT(ptrace(PTRACE_ATTACH, tid, 0, 0), SyscallFailsWithErrno(EPERM)); 247 }); 248 } 249 250 TEST(PtraceTest, TraceParentNotAllowed) { 251 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) < 1); 252 AutoCapability cap(CAP_SYS_PTRACE, false); 253 254 pid_t const child_pid = fork(); 255 if (child_pid == 0) { 256 TEST_CHECK(CheckPtraceAttach(getppid()) == -1); 257 TEST_PCHECK(errno == EPERM); 258 _exit(0); 259 } 260 ASSERT_THAT(child_pid, SyscallSucceeds()); 261 262 int status; 263 ASSERT_THAT(waitpid(child_pid, &status, 0), SyscallSucceeds()); 264 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 265 << " status " << status; 266 } 267 268 TEST(PtraceTest, TraceNonDescendantNotAllowed) { 269 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) < 1); 270 AutoCapability cap(CAP_SYS_PTRACE, false); 271 272 pid_t const tracee_pid = fork(); 273 if (tracee_pid == 0) { 274 while (true) { 275 SleepSafe(absl::Seconds(1)); 276 } 277 } 278 ASSERT_THAT(tracee_pid, SyscallSucceeds()); 279 280 pid_t const tracer_pid = fork(); 281 if (tracer_pid == 0) { 282 TEST_CHECK(CheckPtraceAttach(tracee_pid) == -1); 283 TEST_PCHECK(errno == EPERM); 284 _exit(0); 285 } 286 EXPECT_THAT(tracer_pid, SyscallSucceeds()); 287 288 // Clean up tracer. 289 int status; 290 ASSERT_THAT(waitpid(tracer_pid, &status, 0), SyscallSucceeds()); 291 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); 292 293 // Clean up tracee. 294 ASSERT_THAT(kill(tracee_pid, SIGKILL), SyscallSucceeds()); 295 ASSERT_THAT(waitpid(tracee_pid, &status, 0), 296 SyscallSucceedsWithValue(tracee_pid)); 297 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 298 << " status " << status; 299 } 300 301 TEST(PtraceTest, TraceNonDescendantWithCapabilityAllowed) { 302 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_PTRACE))); 303 // Skip if disallowed by YAMA despite having CAP_SYS_PTRACE. 304 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) > 2); 305 306 pid_t const tracee_pid = fork(); 307 if (tracee_pid == 0) { 308 while (true) { 309 SleepSafe(absl::Seconds(1)); 310 } 311 } 312 ASSERT_THAT(tracee_pid, SyscallSucceeds()); 313 314 pid_t const tracer_pid = fork(); 315 if (tracer_pid == 0) { 316 TEST_PCHECK(CheckPtraceAttach(tracee_pid) == 0); 317 _exit(0); 318 } 319 ASSERT_THAT(tracer_pid, SyscallSucceeds()); 320 321 // Clean up tracer. 322 int status; 323 ASSERT_THAT(waitpid(tracer_pid, &status, 0), SyscallSucceeds()); 324 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); 325 326 // Clean up tracee. 327 ASSERT_THAT(kill(tracee_pid, SIGKILL), SyscallSucceeds()); 328 ASSERT_THAT(waitpid(tracee_pid, &status, 0), 329 SyscallSucceedsWithValue(tracee_pid)); 330 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 331 << " status " << status; 332 } 333 334 TEST(PtraceTest, TraceDescendantsAllowed) { 335 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) > 1); 336 AutoCapability cap(CAP_SYS_PTRACE, false); 337 338 // Use socket pair to communicate tids to this process from its grandchild. 339 int sockets[2]; 340 ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets), SyscallSucceeds()); 341 342 // Allocate vector before forking (not async-signal-safe). 343 ExecveArray const owned_child_argv = { 344 "/proc/self/exe", "--ptrace_test_trace_descendants_allowed", 345 "--ptrace_test_fd", std::to_string(sockets[0])}; 346 char* const* const child_argv = owned_child_argv.get(); 347 348 pid_t const child_pid = fork(); 349 if (child_pid == 0) { 350 // In child process. 351 TEST_PCHECK(close(sockets[1]) == 0); 352 pid_t const grandchild_pid = fork(); 353 if (grandchild_pid == 0) { 354 // This test will create a new thread in the grandchild process. 355 // pthread_create(2) isn't async-signal-safe, so we execve() first. 356 execve(child_argv[0], child_argv, /* envp = */ nullptr); 357 TEST_PCHECK_MSG(false, "Survived execve to test child"); 358 } 359 TEST_PCHECK(grandchild_pid > 0); 360 MaybeSave(); 361 362 // Wait for grandchild. Our parent process will kill it once it's done. 363 int status; 364 TEST_PCHECK(waitpid(grandchild_pid, &status, 0) == grandchild_pid); 365 TEST_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL); 366 MaybeSave(); 367 _exit(0); 368 } 369 ASSERT_THAT(child_pid, SyscallSucceeds()); 370 ASSERT_THAT(close(sockets[0]), SyscallSucceeds()); 371 372 // We should be able to attach to any thread in the grandchild. 373 pid_t grandchild_tid1, grandchild_tid2; 374 ASSERT_THAT(read(sockets[1], &grandchild_tid1, sizeof(grandchild_tid1)), 375 SyscallSucceedsWithValue(sizeof(grandchild_tid1))); 376 ASSERT_THAT(read(sockets[1], &grandchild_tid2, sizeof(grandchild_tid2)), 377 SyscallSucceedsWithValue(sizeof(grandchild_tid2))); 378 379 EXPECT_THAT(CheckPtraceAttach(grandchild_tid1), SyscallSucceeds()); 380 EXPECT_THAT(CheckPtraceAttach(grandchild_tid2), SyscallSucceeds()); 381 382 // Clean up grandchild. 383 ASSERT_THAT(kill(grandchild_tid1, SIGKILL), SyscallSucceeds()); 384 385 // Clean up child. 386 int status; 387 ASSERT_THAT(waitpid(child_pid, &status, 0), 388 SyscallSucceedsWithValue(child_pid)); 389 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 390 << " status " << status; 391 } 392 393 [[noreturn]] void RunTraceDescendantsAllowed(int fd) { 394 // Let the tracer know our tid through the socket fd. 395 pid_t const tid = gettid(); 396 TEST_PCHECK(write(fd, &tid, sizeof(tid)) == sizeof(tid)); 397 MaybeSave(); 398 399 ScopedThread t([fd] { 400 // See if any arbitrary thread (whose tid differs from the process id) can 401 // be traced as well. 402 pid_t const tid = gettid(); 403 TEST_PCHECK(write(fd, &tid, sizeof(tid)) == sizeof(tid)); 404 MaybeSave(); 405 while (true) { 406 SleepSafe(absl::Seconds(1)); 407 } 408 }); 409 410 while (true) { 411 SleepSafe(absl::Seconds(1)); 412 } 413 } 414 415 TEST(PtraceTest, PrctlSetPtracerInvalidPID) { 416 // EINVAL should also be returned if PR_SET_PTRACER is not supported. 417 EXPECT_THAT(prctl(PR_SET_PTRACER, 123456789), SyscallFailsWithErrno(EINVAL)); 418 } 419 420 SimpleSubprocess CreatePtraceAttacherSubprocess() { 421 return SimpleSubprocess("--ptrace_test_ptrace_attacher"); 422 } 423 424 [[noreturn]] static void RunPtraceAttacher(int sockfd) { 425 // execve() may have restored CAP_SYS_PTRACE if we had real UID 0. 426 TEST_CHECK(SetCapability(CAP_SYS_PTRACE, false).ok()); 427 // Perform PTRACE_ATTACH in a separate thread to verify that permissions 428 // apply process-wide. 429 ScopedThread t([&] { 430 while (true) { 431 pid_t pid; 432 int rv = read(sockfd, &pid, sizeof(pid)); 433 if (rv == 0) { 434 _exit(0); 435 } 436 if (rv < 0) { 437 _exit(1); 438 } 439 int resp_errno = 0; 440 if (CheckPtraceAttach(pid) < 0) { 441 resp_errno = errno; 442 } 443 TEST_PCHECK(write(sockfd, &resp_errno, sizeof(resp_errno)) == 444 sizeof(resp_errno)); 445 } 446 }); 447 while (true) { 448 SleepSafe(absl::Seconds(1)); 449 } 450 } 451 452 SimpleSubprocess CreatePrctlSetPtracerSubprocess() { 453 return SimpleSubprocess("--ptrace_test_prctl_set_ptracer"); 454 } 455 456 [[noreturn]] static void RunPrctlSetPtracer(int sockfd) { 457 // Perform prctl in a separate thread to verify that it applies 458 // process-wide. 459 ScopedThread t([&] { 460 while (true) { 461 pid_t pid; 462 int rv = read(sockfd, &pid, sizeof(pid)); 463 if (rv == 0) { 464 _exit(0); 465 } 466 if (rv < 0) { 467 _exit(1); 468 } 469 int resp_errno = 0; 470 if (prctl(PR_SET_PTRACER, pid) < 0) { 471 resp_errno = errno; 472 } 473 TEST_PCHECK(write(sockfd, &resp_errno, sizeof(resp_errno)) == 474 sizeof(resp_errno)); 475 } 476 }); 477 while (true) { 478 SleepSafe(absl::Seconds(1)); 479 } 480 } 481 482 TEST(PtraceTest, PrctlSetPtracer) { 483 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) != 1); 484 485 AutoCapability cap(CAP_SYS_PTRACE, false); 486 487 // Ensure that initially, no tracer exception is set. 488 ASSERT_THAT(prctl(PR_SET_PTRACER, 0), SyscallSucceeds()); 489 490 SimpleSubprocess tracee = CreatePrctlSetPtracerSubprocess(); 491 SimpleSubprocess tracer = CreatePtraceAttacherSubprocess(); 492 493 // By default, Yama should prevent tracer from tracing its parent (this 494 // process) or siblings (tracee). 495 EXPECT_THAT(tracer.Cmd(gettid()), PosixErrorIs(EPERM)); 496 EXPECT_THAT(tracer.Cmd(tracee.pid()), PosixErrorIs(EPERM)); 497 498 // If tracee invokes PR_SET_PTRACER on either tracer's pid, the pid of any of 499 // its ancestors (i.e. us), or PR_SET_PTRACER_ANY, then tracer can trace it 500 // (but not us). 501 502 ASSERT_THAT(tracee.Cmd(tracer.pid()), PosixErrorIs(0)); 503 EXPECT_THAT(tracer.Cmd(tracee.pid()), PosixErrorIs(0)); 504 EXPECT_THAT(tracer.Cmd(gettid()), PosixErrorIs(EPERM)); 505 506 ASSERT_THAT(tracee.Cmd(gettid()), PosixErrorIs(0)); 507 EXPECT_THAT(tracer.Cmd(tracee.pid()), PosixErrorIs(0)); 508 EXPECT_THAT(tracer.Cmd(gettid()), PosixErrorIs(EPERM)); 509 510 ASSERT_THAT(tracee.Cmd(static_cast<pid_t>(PR_SET_PTRACER_ANY)), 511 PosixErrorIs(0)); 512 EXPECT_THAT(tracer.Cmd(tracee.pid()), PosixErrorIs(0)); 513 EXPECT_THAT(tracer.Cmd(gettid()), PosixErrorIs(EPERM)); 514 515 // If tracee invokes PR_SET_PTRACER with pid 0, then tracer can no longer 516 // trace it. 517 ASSERT_THAT(tracee.Cmd(0), PosixErrorIs(0)); 518 EXPECT_THAT(tracer.Cmd(tracee.pid()), PosixErrorIs(EPERM)); 519 520 // If we invoke PR_SET_PTRACER with tracer's pid, then it can trace us (but 521 // not our descendants). 522 ASSERT_THAT(prctl(PR_SET_PTRACER, tracer.pid()), SyscallSucceeds()); 523 EXPECT_THAT(tracer.Cmd(gettid()), PosixErrorIs(0)); 524 EXPECT_THAT(tracer.Cmd(tracee.pid()), PosixErrorIs(EPERM)); 525 526 // If we invoke PR_SET_PTRACER with pid 0, then tracer can no longer trace us. 527 ASSERT_THAT(prctl(PR_SET_PTRACER, 0), SyscallSucceeds()); 528 EXPECT_THAT(tracer.Cmd(gettid()), PosixErrorIs(EPERM)); 529 530 // Another thread in our thread group can invoke PR_SET_PTRACER instead; its 531 // effect applies to the whole thread group. 532 pid_t const our_tid = gettid(); 533 ScopedThread([&] { 534 ASSERT_THAT(prctl(PR_SET_PTRACER, tracer.pid()), SyscallSucceeds()); 535 EXPECT_THAT(tracer.Cmd(gettid()), PosixErrorIs(0)); 536 EXPECT_THAT(tracer.Cmd(our_tid), PosixErrorIs(0)); 537 538 ASSERT_THAT(prctl(PR_SET_PTRACER, 0), SyscallSucceeds()); 539 EXPECT_THAT(tracer.Cmd(gettid()), PosixErrorIs(EPERM)); 540 EXPECT_THAT(tracer.Cmd(our_tid), PosixErrorIs(EPERM)); 541 }).Join(); 542 } 543 544 // Tests that YAMA exceptions store tracees by thread group leader. Exceptions 545 // are preserved even after the tracee thread exits, as long as the tracee's 546 // thread group leader is still around. 547 TEST(PtraceTest, PrctlSetPtracerPersistsPastTraceeThreadExit) { 548 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) != 1); 549 AutoCapability cap(CAP_SYS_PTRACE, false); 550 551 // Use sockets to synchronize between tracer and tracee. 552 int sockets[2]; 553 ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets), SyscallSucceeds()); 554 555 // Allocate vector before forking (not async-signal-safe). 556 ExecveArray const owned_child_argv = { 557 "/proc/self/exe", 558 "--ptrace_test_prctl_set_ptracer_and_exit_tracee_thread", 559 "--ptrace_test_fd", std::to_string(sockets[0])}; 560 char* const* const child_argv = owned_child_argv.get(); 561 562 pid_t const tracee_pid = fork(); 563 if (tracee_pid == 0) { 564 // This test will create a new thread in the child process. 565 // pthread_create(2) isn't async-signal-safe, so we execve() first. 566 TEST_PCHECK(close(sockets[1]) == 0); 567 execve(child_argv[0], child_argv, /* envp = */ nullptr); 568 TEST_PCHECK_MSG(false, "Survived execve to test child"); 569 } 570 ASSERT_THAT(tracee_pid, SyscallSucceeds()); 571 ASSERT_THAT(close(sockets[0]), SyscallSucceeds()); 572 573 pid_t const tracer_pid = fork(); 574 if (tracer_pid == 0) { 575 // Wait until the tracee thread calling prctl has terminated. 576 char done; 577 TEST_PCHECK(read(sockets[1], &done, 1) == 1); 578 MaybeSave(); 579 580 TEST_PCHECK(CheckPtraceAttach(tracee_pid) == 0); 581 _exit(0); 582 } 583 ASSERT_THAT(tracer_pid, SyscallSucceeds()); 584 585 // Clean up tracer. 586 int status; 587 ASSERT_THAT(waitpid(tracer_pid, &status, 0), SyscallSucceeds()); 588 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 589 << " status " << status; 590 591 // Clean up tracee. 592 ASSERT_THAT(kill(tracee_pid, SIGKILL), SyscallSucceeds()); 593 ASSERT_THAT(waitpid(tracee_pid, &status, 0), 594 SyscallSucceedsWithValue(tracee_pid)); 595 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 596 << " status " << status; 597 } 598 599 [[noreturn]] void RunPrctlSetPtracerPersistsPastTraceeThreadExit(int fd) { 600 ScopedThread t([] { 601 TEST_PCHECK(prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) == 0); 602 MaybeSave(); 603 }); 604 t.Join(); 605 // Indicate that thread setting the prctl has exited. 606 TEST_PCHECK(write(fd, "x", 1) == 1); 607 MaybeSave(); 608 609 while (true) { 610 SleepSafe(absl::Seconds(1)); 611 } 612 } 613 614 // Tests that YAMA exceptions store tracees by thread group leader. Exceptions 615 // are preserved across exec as long as the thread group leader does not change, 616 // even if the tracee thread is terminated. 617 TEST(PtraceTest, PrctlSetPtracerPersistsPastLeaderExec) { 618 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) != 1); 619 AutoCapability cap(CAP_SYS_PTRACE, false); 620 621 // Use sockets to synchronize between tracer and tracee. 622 int sockets[2]; 623 ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets), SyscallSucceeds()); 624 625 // Allocate vector before forking (not async-signal-safe). 626 ExecveArray const owned_child_argv = { 627 "/proc/self/exe", "--ptrace_test_tracee", "--ptrace_test_fd", 628 std::to_string(sockets[0])}; 629 char* const* const child_argv = owned_child_argv.get(); 630 631 pid_t const tracee_pid = fork(); 632 if (tracee_pid == 0) { 633 TEST_PCHECK(close(sockets[1]) == 0); 634 TEST_PCHECK(prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) == 0); 635 MaybeSave(); 636 637 // This test will create a new thread in the child process. 638 // pthread_create(2) isn't async-signal-safe, so we execve() first. 639 execve(child_argv[0], child_argv, /* envp = */ nullptr); 640 TEST_PCHECK_MSG(false, "Survived execve to test child"); 641 } 642 ASSERT_THAT(tracee_pid, SyscallSucceeds()); 643 ASSERT_THAT(close(sockets[0]), SyscallSucceeds()); 644 645 pid_t const tracer_pid = fork(); 646 if (tracer_pid == 0) { 647 // Wait until the tracee has exec'd. 648 char done; 649 TEST_PCHECK(read(sockets[1], &done, 1) == 1); 650 MaybeSave(); 651 652 TEST_PCHECK(CheckPtraceAttach(tracee_pid) == 0); 653 _exit(0); 654 } 655 ASSERT_THAT(tracer_pid, SyscallSucceeds()); 656 657 // Clean up tracer. 658 int status; 659 ASSERT_THAT(waitpid(tracer_pid, &status, 0), SyscallSucceeds()); 660 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 661 << " status " << status; 662 663 // Clean up tracee. 664 ASSERT_THAT(kill(tracee_pid, SIGKILL), SyscallSucceeds()); 665 ASSERT_THAT(waitpid(tracee_pid, &status, 0), 666 SyscallSucceedsWithValue(tracee_pid)); 667 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 668 << " status " << status; 669 } 670 671 [[noreturn]] void RunTracee(int fd) { 672 // Indicate that we have exec'd. 673 TEST_PCHECK(write(fd, "x", 1) == 1); 674 MaybeSave(); 675 676 while (true) { 677 SleepSafe(absl::Seconds(1)); 678 } 679 } 680 681 // Tests that YAMA exceptions store tracees by thread group leader. Exceptions 682 // are cleared if the tracee process's thread group leader is terminated by 683 // exec. 684 TEST(PtraceTest, PrctlSetPtracerDoesNotPersistPastNonLeaderExec) { 685 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) != 1); 686 AutoCapability cap(CAP_SYS_PTRACE, false); 687 688 // Use sockets to synchronize between tracer and tracee. 689 int sockets[2]; 690 ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets), SyscallSucceeds()); 691 692 // Allocate vector before forking (not async-signal-safe). 693 ExecveArray const owned_child_argv = { 694 "/proc/self/exe", "--ptrace_test_prctl_set_ptracer_and_exec_non_leader", 695 "--ptrace_test_fd", std::to_string(sockets[0])}; 696 char* const* const child_argv = owned_child_argv.get(); 697 698 pid_t const tracee_pid = fork(); 699 if (tracee_pid == 0) { 700 // This test will create a new thread in the child process. 701 // pthread_create(2) isn't async-signal-safe, so we execve() first. 702 TEST_PCHECK(close(sockets[1]) == 0); 703 execve(child_argv[0], child_argv, /* envp = */ nullptr); 704 TEST_PCHECK_MSG(false, "Survived execve to test child"); 705 } 706 ASSERT_THAT(tracee_pid, SyscallSucceeds()); 707 ASSERT_THAT(close(sockets[0]), SyscallSucceeds()); 708 709 pid_t const tracer_pid = fork(); 710 if (tracer_pid == 0) { 711 // Wait until the tracee has exec'd. 712 char done; 713 TEST_PCHECK(read(sockets[1], &done, 1) == 1); 714 MaybeSave(); 715 716 TEST_CHECK(CheckPtraceAttach(tracee_pid) == -1); 717 TEST_PCHECK(errno == EPERM); 718 _exit(0); 719 } 720 ASSERT_THAT(tracer_pid, SyscallSucceeds()); 721 722 // Clean up tracer. 723 int status; 724 ASSERT_THAT(waitpid(tracer_pid, &status, 0), SyscallSucceeds()); 725 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 726 << " status " << status; 727 728 // Clean up tracee. 729 ASSERT_THAT(kill(tracee_pid, SIGKILL), SyscallSucceeds()); 730 ASSERT_THAT(waitpid(tracee_pid, &status, 0), 731 SyscallSucceedsWithValue(tracee_pid)); 732 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 733 << " status " << status; 734 } 735 736 [[noreturn]] void RunPrctlSetPtracerDoesNotPersistPastNonLeaderExec(int fd) { 737 ScopedThread t([fd] { 738 TEST_PCHECK(prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) == 0); 739 MaybeSave(); 740 741 ExecveArray const owned_child_argv = { 742 "/proc/self/exe", "--ptrace_test_tracee", "--ptrace_test_fd", 743 std::to_string(fd)}; 744 char* const* const child_argv = owned_child_argv.get(); 745 746 execve(child_argv[0], child_argv, /* envp = */ nullptr); 747 TEST_PCHECK_MSG(false, "Survived execve to test child"); 748 }); 749 t.Join(); 750 TEST_CHECK_MSG(false, "Survived execve? (main)"); 751 _exit(1); 752 } 753 754 // Tests that YAMA exceptions store the tracer itself rather than the thread 755 // group leader. Exceptions are cleared when the tracer task exits, rather than 756 // when its thread group leader exits. 757 TEST(PtraceTest, PrctlSetPtracerDoesNotPersistPastTracerThreadExit) { 758 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) != 1); 759 760 // Use sockets to synchronize between tracer and tracee. 761 int sockets[2]; 762 ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets), SyscallSucceeds()); 763 764 pid_t const tracee_pid = fork(); 765 if (tracee_pid == 0) { 766 TEST_PCHECK(close(sockets[1]) == 0); 767 pid_t tracer_tid; 768 TEST_PCHECK(read(sockets[0], &tracer_tid, sizeof(tracer_tid)) == 769 sizeof(tracer_tid)); 770 MaybeSave(); 771 772 TEST_PCHECK(prctl(PR_SET_PTRACER, tracer_tid) == 0); 773 MaybeSave(); 774 // Indicate that the prctl has been set. 775 TEST_PCHECK(write(sockets[0], "x", 1) == 1); 776 MaybeSave(); 777 778 while (true) { 779 SleepSafe(absl::Seconds(1)); 780 } 781 } 782 ASSERT_THAT(tracee_pid, SyscallSucceeds()); 783 ASSERT_THAT(close(sockets[0]), SyscallSucceeds()); 784 785 // Allocate vector before forking (not async-signal-safe). 786 ExecveArray const owned_child_argv = { 787 "/proc/self/exe", 788 "--ptrace_test_prctl_set_ptracer_and_exit_tracer_thread", 789 "--ptrace_test_prctl_set_ptracer_and_exit_tracer_thread_tid", 790 std::to_string(tracee_pid), 791 "--ptrace_test_fd", 792 std::to_string(sockets[1])}; 793 char* const* const child_argv = owned_child_argv.get(); 794 795 pid_t const tracer_pid = fork(); 796 if (tracer_pid == 0) { 797 // This test will create a new thread in the child process. 798 // pthread_create(2) isn't async-signal-safe, so we execve() first. 799 execve(child_argv[0], child_argv, /* envp = */ nullptr); 800 TEST_PCHECK_MSG(false, "Survived execve to test child"); 801 } 802 ASSERT_THAT(tracer_pid, SyscallSucceeds()); 803 804 // Clean up tracer. 805 int status; 806 ASSERT_THAT(waitpid(tracer_pid, &status, 0), SyscallSucceeds()); 807 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 808 << " status " << status; 809 810 // Clean up tracee. 811 ASSERT_THAT(kill(tracee_pid, SIGKILL), SyscallSucceeds()); 812 ASSERT_THAT(waitpid(tracee_pid, &status, 0), 813 SyscallSucceedsWithValue(tracee_pid)); 814 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 815 << " status " << status; 816 } 817 818 [[noreturn]] void RunPrctlSetPtracerDoesNotPersistPastTracerThreadExit( 819 int tracee_tid, int fd) { 820 AutoCapability cap(CAP_SYS_PTRACE, false); 821 822 ScopedThread t([fd] { 823 pid_t const tracer_tid = gettid(); 824 TEST_PCHECK(write(fd, &tracer_tid, sizeof(tracer_tid)) == 825 sizeof(tracer_tid)); 826 827 // Wait until the prctl has been set. 828 char done; 829 TEST_PCHECK(read(fd, &done, 1) == 1); 830 MaybeSave(); 831 }); 832 t.Join(); 833 834 // Sleep for a bit before verifying the invalidation. The thread exit above 835 // should cause the ptrace exception to be invalidated, but in Linux, this is 836 // not done immediately. The YAMA exception is dropped during 837 // __put_task_struct(), which occurs (at the earliest) one RCU grace period 838 // after exit_notify() ==> release_task(). 839 SleepSafe(absl::Milliseconds(100)); 840 841 TEST_CHECK(CheckPtraceAttach(tracee_tid) == -1); 842 TEST_PCHECK(errno == EPERM); 843 _exit(0); 844 } 845 846 // Tests that YAMA exceptions store the tracer thread itself rather than the 847 // thread group leader. Exceptions are preserved across exec in the tracer 848 // thread, even if the thread group leader is terminated. 849 TEST(PtraceTest, PrctlSetPtracerRespectsTracerThreadID) { 850 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) != 1); 851 852 // Use sockets to synchronize between tracer and tracee. 853 int sockets[2]; 854 ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets), SyscallSucceeds()); 855 856 pid_t const tracee_pid = fork(); 857 if (tracee_pid == 0) { 858 TEST_PCHECK(close(sockets[1]) == 0); 859 pid_t tracer_tid; 860 TEST_PCHECK(read(sockets[0], &tracer_tid, sizeof(tracer_tid)) == 861 sizeof(tracer_tid)); 862 MaybeSave(); 863 864 TEST_PCHECK(prctl(PR_SET_PTRACER, tracer_tid) == 0); 865 MaybeSave(); 866 // Indicate that the prctl has been set. 867 TEST_PCHECK(write(sockets[0], "x", 1) == 1); 868 MaybeSave(); 869 870 while (true) { 871 SleepSafe(absl::Seconds(1)); 872 } 873 } 874 ASSERT_THAT(tracee_pid, SyscallSucceeds()); 875 ASSERT_THAT(close(sockets[0]), SyscallSucceeds()); 876 877 // Allocate vector before forking (not async-signal-safe). 878 ExecveArray const owned_child_argv = { 879 "/proc/self/exe", 880 "--ptrace_test_prctl_set_ptracer_respects_tracer_thread_id", 881 "--ptrace_test_prctl_set_ptracer_respects_tracer_thread_id_tid", 882 std::to_string(tracee_pid), 883 "--ptrace_test_fd", 884 std::to_string(sockets[1])}; 885 char* const* const child_argv = owned_child_argv.get(); 886 887 pid_t const tracer_pid = fork(); 888 if (tracer_pid == 0) { 889 // This test will create a new thread in the child process. 890 // pthread_create(2) isn't async-signal-safe, so we execve() first. 891 execve(child_argv[0], child_argv, /* envp = */ nullptr); 892 TEST_PCHECK_MSG(false, "Survived execve to test child"); 893 } 894 ASSERT_THAT(tracer_pid, SyscallSucceeds()); 895 896 // Clean up tracer. 897 int status; 898 ASSERT_THAT(waitpid(tracer_pid, &status, 0), SyscallSucceeds()); 899 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 900 << " status " << status; 901 902 // Clean up tracee. 903 ASSERT_THAT(kill(tracee_pid, SIGKILL), SyscallSucceeds()); 904 ASSERT_THAT(waitpid(tracee_pid, &status, 0), 905 SyscallSucceedsWithValue(tracee_pid)); 906 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 907 << " status " << status; 908 } 909 910 [[noreturn]] void RunPrctlSetPtracerRespectsTracerThreadID(int tracee_tid, 911 int fd) { 912 // Create a separate thread for tracing (i.e., not the thread group 913 // leader). After the subsequent execve(), the current thread group leader 914 // will no longer be exist, but the YAMA exception installed with this 915 // thread should still be valid. 916 ScopedThread t([tracee_tid, fd] { 917 pid_t const tracer_tid = gettid(); 918 TEST_PCHECK(write(fd, &tracer_tid, sizeof(tracer_tid))); 919 MaybeSave(); 920 921 // Wait until the tracee has made the PR_SET_PTRACER prctl. 922 char done; 923 TEST_PCHECK(read(fd, &done, 1) == 1); 924 MaybeSave(); 925 926 ExecveArray const owned_child_argv = { 927 "/proc/self/exe", "--ptrace_test_trace_tid", std::to_string(tracee_tid), 928 "--ptrace_test_fd", std::to_string(fd)}; 929 char* const* const child_argv = owned_child_argv.get(); 930 931 execve(child_argv[0], child_argv, /* envp = */ nullptr); 932 TEST_PCHECK_MSG(false, "Survived execve to test child"); 933 }); 934 t.Join(); 935 TEST_CHECK_MSG(false, "Survived execve? (main)"); 936 _exit(1); 937 } 938 939 [[noreturn]] void RunTraceTID(int tracee_tid, int fd) { 940 TEST_PCHECK(SetCapability(CAP_SYS_PTRACE, false).ok()); 941 TEST_PCHECK(CheckPtraceAttach(tracee_tid) == 0); 942 _exit(0); 943 } 944 945 // Tests that removing a YAMA exception does not affect a tracer that is already 946 // attached. 947 TEST(PtraceTest, PrctlClearPtracerDoesNotAffectCurrentTracer) { 948 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) != 1); 949 AutoCapability cap(CAP_SYS_PTRACE, false); 950 951 // Use sockets to synchronize between tracer and tracee. 952 int sockets[2]; 953 ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets), SyscallSucceeds()); 954 955 pid_t const tracee_pid = fork(); 956 if (tracee_pid == 0) { 957 TEST_PCHECK(close(sockets[1]) == 0); 958 TEST_PCHECK(prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) == 0); 959 MaybeSave(); 960 // Indicate that the prctl has been set. 961 TEST_PCHECK(write(sockets[0], "x", 1) == 1); 962 MaybeSave(); 963 964 // Wait until tracer has attached before clearing PR_SET_PTRACER. 965 char done; 966 TEST_PCHECK(read(sockets[0], &done, 1) == 1); 967 MaybeSave(); 968 969 TEST_PCHECK(prctl(PR_SET_PTRACER, 0) == 0); 970 MaybeSave(); 971 // Indicate that the prctl has been set. 972 TEST_PCHECK(write(sockets[0], "x", 1) == 1); 973 MaybeSave(); 974 975 while (true) { 976 SleepSafe(absl::Seconds(1)); 977 } 978 } 979 ASSERT_THAT(tracee_pid, SyscallSucceeds()); 980 ASSERT_THAT(close(sockets[0]), SyscallSucceeds()); 981 982 std::string mem_path = "/proc/" + std::to_string(tracee_pid) + "/mem"; 983 pid_t const tracer_pid = fork(); 984 if (tracer_pid == 0) { 985 // Wait until tracee has called prctl, or else we won't be able to attach. 986 char done; 987 TEST_PCHECK(read(sockets[1], &done, 1) == 1); 988 MaybeSave(); 989 990 TEST_PCHECK(ptrace(PTRACE_ATTACH, tracee_pid, 0, 0) == 0); 991 MaybeSave(); 992 // Indicate that we have attached. 993 TEST_PCHECK(write(sockets[1], &done, 1) == 1); 994 MaybeSave(); 995 996 // Block until tracee enters signal-delivery-stop as a result of the 997 // SIGSTOP sent by PTRACE_ATTACH. 998 int status; 999 TEST_PCHECK(waitpid(tracee_pid, &status, 0) == tracee_pid); 1000 MaybeSave(); 1001 TEST_CHECK(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP); 1002 MaybeSave(); 1003 1004 TEST_PCHECK(ptrace(PTRACE_CONT, tracee_pid, 0, 0) == 0); 1005 MaybeSave(); 1006 1007 // Wait until tracee has cleared PR_SET_PTRACER. Even though it was cleared, 1008 // we should still be able to access /proc/[pid]/mem because we are already 1009 // attached. 1010 TEST_PCHECK(read(sockets[1], &done, 1) == 1); 1011 MaybeSave(); 1012 TEST_PCHECK(open(mem_path.c_str(), O_RDONLY) != -1); 1013 MaybeSave(); 1014 _exit(0); 1015 } 1016 ASSERT_THAT(tracer_pid, SyscallSucceeds()); 1017 1018 // Clean up tracer. 1019 int status; 1020 ASSERT_THAT(waitpid(tracer_pid, &status, 0), SyscallSucceeds()); 1021 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 1022 << " status " << status; 1023 1024 // Clean up tracee. 1025 ASSERT_THAT(kill(tracee_pid, SIGKILL), SyscallSucceeds()); 1026 ASSERT_THAT(waitpid(tracee_pid, &status, 0), 1027 SyscallSucceedsWithValue(tracee_pid)); 1028 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 1029 << " status " << status; 1030 } 1031 1032 TEST(PtraceTest, PrctlNotInherited) { 1033 SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()) != 1); 1034 AutoCapability cap(CAP_SYS_PTRACE, false); 1035 1036 // Allow any ptracer. This should not affect the child processes. 1037 ASSERT_THAT(prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY), SyscallSucceeds()); 1038 1039 pid_t const tracee_pid = fork(); 1040 if (tracee_pid == 0) { 1041 while (true) { 1042 SleepSafe(absl::Seconds(1)); 1043 } 1044 } 1045 ASSERT_THAT(tracee_pid, SyscallSucceeds()); 1046 1047 pid_t const tracer_pid = fork(); 1048 if (tracer_pid == 0) { 1049 TEST_CHECK(CheckPtraceAttach(tracee_pid) == -1); 1050 TEST_PCHECK(errno == EPERM); 1051 _exit(0); 1052 } 1053 ASSERT_THAT(tracer_pid, SyscallSucceeds()); 1054 1055 // Clean up tracer. 1056 int status; 1057 ASSERT_THAT(waitpid(tracer_pid, &status, 0), SyscallSucceeds()); 1058 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 1059 << " status " << status; 1060 1061 // Clean up tracee. 1062 ASSERT_THAT(kill(tracee_pid, SIGKILL), SyscallSucceeds()); 1063 ASSERT_THAT(waitpid(tracee_pid, &status, 0), 1064 SyscallSucceedsWithValue(tracee_pid)); 1065 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 1066 << " status " << status; 1067 } 1068 1069 TEST(PtraceTest, AttachParent_PeekData_PokeData_SignalSuppression) { 1070 // Yama prevents attaching to a parent. Skip the test if the scope is anything 1071 // except disabled. 1072 const int yama_scope = ASSERT_NO_ERRNO_AND_VALUE(YamaPtraceScope()); 1073 SKIP_IF(yama_scope > 1); 1074 if (yama_scope == 1) { 1075 // Allow child to trace us. 1076 ASSERT_THAT(prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY), SyscallSucceeds()); 1077 } 1078 1079 // Test PTRACE_POKE/PEEKDATA on both anonymous and file mappings. 1080 const auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 1081 ASSERT_NO_ERRNO(Truncate(file.path(), kPageSize)); 1082 const FileDescriptor fd = 1083 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR)); 1084 const auto file_mapping = ASSERT_NO_ERRNO_AND_VALUE(Mmap( 1085 nullptr, kPageSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0)); 1086 1087 constexpr long kBeforePokeDataAnonValue = 10; 1088 constexpr long kAfterPokeDataAnonValue = 20; 1089 constexpr long kBeforePokeDataFileValue = 0; // implicit, due to truncate() 1090 constexpr long kAfterPokeDataFileValue = 30; 1091 1092 volatile long anon_word = kBeforePokeDataAnonValue; 1093 auto* file_word_ptr = static_cast<volatile long*>(file_mapping.ptr()); 1094 1095 pid_t const child_pid = fork(); 1096 if (child_pid == 0) { 1097 // In child process. 1098 1099 // Attach to the parent. 1100 pid_t const parent_pid = getppid(); 1101 TEST_PCHECK(ptrace(PTRACE_ATTACH, parent_pid, 0, 0) == 0); 1102 MaybeSave(); 1103 1104 // Block until the parent enters signal-delivery-stop as a result of the 1105 // SIGSTOP sent by PTRACE_ATTACH. 1106 int status; 1107 TEST_PCHECK(waitpid(parent_pid, &status, 0) == parent_pid); 1108 MaybeSave(); 1109 TEST_CHECK(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP); 1110 1111 // Replace the value of anon_word in the parent process with 1112 // kAfterPokeDataAnonValue. 1113 long parent_word = ptrace(PTRACE_PEEKDATA, parent_pid, &anon_word, 0); 1114 MaybeSave(); 1115 TEST_CHECK(parent_word == kBeforePokeDataAnonValue); 1116 TEST_PCHECK(ptrace(PTRACE_POKEDATA, parent_pid, &anon_word, 1117 kAfterPokeDataAnonValue) == 0); 1118 MaybeSave(); 1119 1120 // Replace the value pointed to by file_word_ptr in the mapped file with 1121 // kAfterPokeDataFileValue, via the parent process' mapping. 1122 parent_word = ptrace(PTRACE_PEEKDATA, parent_pid, file_word_ptr, 0); 1123 MaybeSave(); 1124 TEST_CHECK(parent_word == kBeforePokeDataFileValue); 1125 TEST_PCHECK(ptrace(PTRACE_POKEDATA, parent_pid, file_word_ptr, 1126 kAfterPokeDataFileValue) == 0); 1127 MaybeSave(); 1128 1129 // Detach from the parent and suppress the SIGSTOP. If the SIGSTOP is not 1130 // suppressed, the parent will hang in group-stop, causing the test to time 1131 // out. 1132 TEST_PCHECK(ptrace(PTRACE_DETACH, parent_pid, 0, 0) == 0); 1133 MaybeSave(); 1134 _exit(0); 1135 } 1136 // In parent process. 1137 ASSERT_THAT(child_pid, SyscallSucceeds()); 1138 1139 // Wait for the child to complete. 1140 int status; 1141 ASSERT_THAT(waitpid(child_pid, &status, 0), 1142 SyscallSucceedsWithValue(child_pid)); 1143 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 1144 << " status " << status; 1145 1146 // Check that the child's PTRACE_POKEDATA was effective. 1147 EXPECT_EQ(kAfterPokeDataAnonValue, anon_word); 1148 EXPECT_EQ(kAfterPokeDataFileValue, *file_word_ptr); 1149 } 1150 1151 TEST(PtraceTest, GetSigMask) { 1152 // glibc and the Linux kernel define a sigset_t with different sizes. To avoid 1153 // creating a kernel_sigset_t and recreating all the modification functions 1154 // (sigemptyset, etc), we just hardcode the kernel sigset size. 1155 constexpr int kSizeofKernelSigset = 8; 1156 constexpr int kBlockSignal = SIGUSR1; 1157 sigset_t blocked; 1158 sigemptyset(&blocked); 1159 sigaddset(&blocked, kBlockSignal); 1160 1161 pid_t const child_pid = fork(); 1162 if (child_pid == 0) { 1163 // In child process. 1164 1165 // Install a signal handler for kBlockSignal to avoid termination and block 1166 // it. 1167 TEST_PCHECK(signal( 1168 kBlockSignal, +[](int signo) {}) != SIG_ERR); 1169 MaybeSave(); 1170 TEST_PCHECK(sigprocmask(SIG_SETMASK, &blocked, nullptr) == 0); 1171 MaybeSave(); 1172 1173 // Enable tracing. 1174 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 1175 MaybeSave(); 1176 1177 // This should be blocked. 1178 RaiseSignal(kBlockSignal); 1179 1180 // This should be suppressed by parent, who will change signal mask in the 1181 // meantime, which means kBlockSignal should be delivered once this resumes. 1182 RaiseSignal(SIGSTOP); 1183 1184 _exit(0); 1185 } 1186 // In parent process. 1187 ASSERT_THAT(child_pid, SyscallSucceeds()); 1188 1189 // Wait for the child to send itself SIGSTOP and enter signal-delivery-stop. 1190 int status; 1191 ASSERT_THAT(waitpid(child_pid, &status, 0), 1192 SyscallSucceedsWithValue(child_pid)); 1193 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 1194 << " status " << status; 1195 1196 // Get current signal mask. 1197 sigset_t set; 1198 EXPECT_THAT(ptrace(kPtraceGetSigMask, child_pid, kSizeofKernelSigset, &set), 1199 SyscallSucceeds()); 1200 EXPECT_THAT(blocked, EqualsSigset(set)); 1201 1202 // Try to get current signal mask with bad size argument. 1203 EXPECT_THAT(ptrace(kPtraceGetSigMask, child_pid, 0, nullptr), 1204 SyscallFailsWithErrno(EINVAL)); 1205 1206 // Try to set bad signal mask. 1207 sigset_t* bad_addr = reinterpret_cast<sigset_t*>(-1); 1208 EXPECT_THAT( 1209 ptrace(kPtraceSetSigMask, child_pid, kSizeofKernelSigset, bad_addr), 1210 SyscallFailsWithErrno(EFAULT)); 1211 1212 // Set signal mask to empty set. 1213 sigset_t set1; 1214 sigemptyset(&set1); 1215 EXPECT_THAT(ptrace(kPtraceSetSigMask, child_pid, kSizeofKernelSigset, &set1), 1216 SyscallSucceeds()); 1217 1218 // Suppress SIGSTOP and resume the child. It should re-enter 1219 // signal-delivery-stop for kBlockSignal. 1220 ASSERT_THAT(ptrace(PTRACE_CONT, child_pid, 0, 0), SyscallSucceeds()); 1221 ASSERT_THAT(waitpid(child_pid, &status, 0), 1222 SyscallSucceedsWithValue(child_pid)); 1223 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == kBlockSignal) 1224 << " status " << status; 1225 1226 ASSERT_THAT(ptrace(PTRACE_CONT, child_pid, 0, 0), SyscallSucceeds()); 1227 ASSERT_THAT(waitpid(child_pid, &status, 0), 1228 SyscallSucceedsWithValue(child_pid)); 1229 // Let's see that process exited normally. 1230 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 1231 << " status " << status; 1232 } 1233 1234 TEST(PtraceTest, GetSiginfo_SetSiginfo_SignalInjection) { 1235 constexpr int kOriginalSigno = SIGUSR1; 1236 constexpr int kInjectedSigno = SIGUSR2; 1237 1238 pid_t const child_pid = fork(); 1239 if (child_pid == 0) { 1240 // In child process. 1241 1242 // Override all signal handlers. 1243 struct sigaction sa = {}; 1244 sa.sa_handler = +[](int signo) { _exit(signo); }; 1245 TEST_PCHECK(sigfillset(&sa.sa_mask) == 0); 1246 for (int signo = 1; signo < 32; signo++) { 1247 if (signo == SIGKILL || signo == SIGSTOP) { 1248 continue; 1249 } 1250 TEST_PCHECK(sigaction(signo, &sa, nullptr) == 0); 1251 } 1252 for (int signo = SIGRTMIN; signo <= SIGRTMAX; signo++) { 1253 TEST_PCHECK(sigaction(signo, &sa, nullptr) == 0); 1254 } 1255 1256 // Unblock all signals. 1257 TEST_PCHECK(sigprocmask(SIG_UNBLOCK, &sa.sa_mask, nullptr) == 0); 1258 MaybeSave(); 1259 1260 // Send ourselves kOriginalSignal while ptraced and exit with the signal we 1261 // actually receive via the signal handler, if any, or 0 if we don't receive 1262 // a signal. 1263 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 1264 MaybeSave(); 1265 RaiseSignal(kOriginalSigno); 1266 _exit(0); 1267 } 1268 // In parent process. 1269 ASSERT_THAT(child_pid, SyscallSucceeds()); 1270 1271 // Wait for the child to send itself kOriginalSigno and enter 1272 // signal-delivery-stop. 1273 int status; 1274 ASSERT_THAT(waitpid(child_pid, &status, 0), 1275 SyscallSucceedsWithValue(child_pid)); 1276 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == kOriginalSigno) 1277 << " status " << status; 1278 1279 siginfo_t siginfo = {}; 1280 ASSERT_THAT(ptrace(PTRACE_GETSIGINFO, child_pid, 0, &siginfo), 1281 SyscallSucceeds()); 1282 EXPECT_EQ(kOriginalSigno, siginfo.si_signo); 1283 EXPECT_EQ(SI_TKILL, siginfo.si_code); 1284 1285 // Replace the signal with kInjectedSigno, and check that the child exits 1286 // with kInjectedSigno, indicating that signal injection was successful. 1287 siginfo.si_signo = kInjectedSigno; 1288 ASSERT_THAT(ptrace(PTRACE_SETSIGINFO, child_pid, 0, &siginfo), 1289 SyscallSucceeds()); 1290 ASSERT_THAT(ptrace(PTRACE_DETACH, child_pid, 0, kInjectedSigno), 1291 SyscallSucceeds()); 1292 ASSERT_THAT(waitpid(child_pid, &status, 0), 1293 SyscallSucceedsWithValue(child_pid)); 1294 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == kInjectedSigno) 1295 << " status " << status; 1296 } 1297 1298 TEST(PtraceTest, SIGKILLDoesNotCauseSignalDeliveryStop) { 1299 pid_t const child_pid = fork(); 1300 if (child_pid == 0) { 1301 // In child process. 1302 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 1303 MaybeSave(); 1304 RaiseSignal(SIGKILL); 1305 TEST_CHECK_MSG(false, "Survived SIGKILL?"); 1306 _exit(1); 1307 } 1308 // In parent process. 1309 ASSERT_THAT(child_pid, SyscallSucceeds()); 1310 1311 // Expect the child to die to SIGKILL without entering signal-delivery-stop. 1312 int status; 1313 ASSERT_THAT(waitpid(child_pid, &status, 0), 1314 SyscallSucceedsWithValue(child_pid)); 1315 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 1316 << " status " << status; 1317 } 1318 1319 TEST(PtraceTest, PtraceKill) { 1320 constexpr int kOriginalSigno = SIGUSR1; 1321 1322 pid_t const child_pid = fork(); 1323 if (child_pid == 0) { 1324 // In child process. 1325 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 1326 MaybeSave(); 1327 1328 // PTRACE_KILL only works if tracee has entered signal-delivery-stop. 1329 RaiseSignal(kOriginalSigno); 1330 TEST_CHECK_MSG(false, "Failed to kill the process?"); 1331 _exit(0); 1332 } 1333 // In parent process. 1334 ASSERT_THAT(child_pid, SyscallSucceeds()); 1335 1336 // Wait for the child to send itself kOriginalSigno and enter 1337 // signal-delivery-stop. 1338 int status; 1339 ASSERT_THAT(waitpid(child_pid, &status, 0), 1340 SyscallSucceedsWithValue(child_pid)); 1341 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == kOriginalSigno) 1342 << " status " << status; 1343 1344 ASSERT_THAT(ptrace(PTRACE_KILL, child_pid, 0, 0), SyscallSucceeds()); 1345 1346 // Expect the child to die with SIGKILL. 1347 ASSERT_THAT(waitpid(child_pid, &status, 0), 1348 SyscallSucceedsWithValue(child_pid)); 1349 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 1350 << " status " << status; 1351 } 1352 1353 TEST(PtraceTest, GetRegSet) { 1354 pid_t const child_pid = fork(); 1355 if (child_pid == 0) { 1356 // In child process. 1357 1358 // Enable tracing. 1359 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 1360 MaybeSave(); 1361 1362 // Use kill explicitly because we check the syscall argument register below. 1363 kill(getpid(), SIGSTOP); 1364 1365 _exit(0); 1366 } 1367 // In parent process. 1368 ASSERT_THAT(child_pid, SyscallSucceeds()); 1369 1370 // Wait for the child to send itself SIGSTOP and enter signal-delivery-stop. 1371 int status; 1372 ASSERT_THAT(waitpid(child_pid, &status, 0), 1373 SyscallSucceedsWithValue(child_pid)); 1374 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 1375 << " status " << status; 1376 1377 // Get the general registers. 1378 struct user_regs_struct regs; 1379 struct iovec iov; 1380 iov.iov_base = ®s; 1381 iov.iov_len = sizeof(regs); 1382 EXPECT_THAT(ptrace(PTRACE_GETREGSET, child_pid, NT_PRSTATUS, &iov), 1383 SyscallSucceeds()); 1384 1385 // Read exactly the full register set. 1386 EXPECT_EQ(iov.iov_len, sizeof(regs)); 1387 1388 #if defined(__x86_64__) 1389 // Child called kill(2), with SIGSTOP as arg 2. 1390 EXPECT_EQ(regs.rsi, SIGSTOP); 1391 #elif defined(__aarch64__) 1392 EXPECT_EQ(regs.regs[1], SIGSTOP); 1393 #endif 1394 1395 // Suppress SIGSTOP and resume the child. 1396 ASSERT_THAT(ptrace(PTRACE_CONT, child_pid, 0, 0), SyscallSucceeds()); 1397 ASSERT_THAT(waitpid(child_pid, &status, 0), 1398 SyscallSucceedsWithValue(child_pid)); 1399 // Let's see that process exited normally. 1400 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 1401 << " status " << status; 1402 } 1403 #if defined(__x86_64__) 1404 #define SYSNO_STR1(x) #x 1405 #define SYSNO_STR(x) SYSNO_STR1(x) 1406 1407 // Check that ptrace works properly when a target process is stopped on a 1408 // system call that is handled via the fast path. 1409 TEST(PtraceTest, ChangeRegSetInOptSyscall) { 1410 constexpr uint64_t kTestRet = 0x111; 1411 constexpr uint64_t kTestRbx1 = 0x333; 1412 constexpr uint64_t kTestRbx2 = 0x333; 1413 constexpr uint64_t kTestRdi = 0x555; 1414 1415 pid_t const child_pid = fork(); 1416 if (child_pid == 0) { 1417 // In child process. 1418 uint64_t ret, rbx = 0, rdi = kTestRdi; 1419 1420 // Enable tracing. 1421 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 1422 MaybeSave(); 1423 1424 // Use kill explicitly because we check the syscall argument register below. 1425 kill(getpid(), SIGSTOP); 1426 1427 // A tested syscall has to be triggered twice, because the first call 1428 // doesn't trigger the fast path. 1429 for (int i = 0; i < 2; i++) { 1430 if (i == 1) rbx = kTestRbx1; 1431 __asm__ __volatile__( 1432 "movl $" SYSNO_STR(SYS_getpid) ", %%eax\n" 1433 "syscall\n" 1434 : "=a"(ret), "=b"(rbx) 1435 : "b"(rbx), "D"(rdi) 1436 : "rcx", "r11", "memory"); 1437 } 1438 1439 TEST_CHECK(ret == kTestRet); 1440 TEST_CHECK(rbx == kTestRbx2); 1441 1442 _exit(0); 1443 } 1444 // In parent process. 1445 ASSERT_THAT(child_pid, SyscallSucceeds()); 1446 1447 // Wait for the child to send itself SIGSTOP and enter signal-delivery-stop. 1448 int status; 1449 ASSERT_THAT(waitpid(child_pid, &status, 0), 1450 SyscallSucceedsWithValue(child_pid)); 1451 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 1452 << " status " << status; 1453 1454 // Stop the child in the second getpid syscall. 1455 for (int i = 0; i < 2; i++) { 1456 ASSERT_THAT(ptrace(PTRACE_SYSEMU, child_pid, 0, 0), SyscallSucceeds()); 1457 ASSERT_THAT(waitpid(child_pid, &status, 0), 1458 SyscallSucceedsWithValue(child_pid)); 1459 } 1460 1461 // Get the general registers. 1462 struct user_regs_struct regs; 1463 struct iovec iov; 1464 iov.iov_base = ®s; 1465 iov.iov_len = sizeof(regs); 1466 EXPECT_THAT(ptrace(PTRACE_GETREGSET, child_pid, NT_PRSTATUS, &iov), 1467 SyscallSucceeds()); 1468 1469 // Read exactly the full register set. 1470 EXPECT_EQ(iov.iov_len, sizeof(regs)); 1471 1472 EXPECT_EQ(regs.rax, -ENOSYS); 1473 EXPECT_EQ(regs.orig_rax, SYS_getpid); 1474 EXPECT_EQ(regs.rdi, kTestRdi); 1475 EXPECT_EQ(regs.rbx, kTestRbx1); 1476 1477 regs.rbx = kTestRbx2; 1478 regs.rax = kTestRet; 1479 EXPECT_THAT(ptrace(PTRACE_SETREGSET, child_pid, NT_PRSTATUS, &iov), 1480 SyscallSucceeds()); 1481 1482 ASSERT_THAT(ptrace(PTRACE_CONT, child_pid, 0, 0), SyscallSucceeds()); 1483 ASSERT_THAT(waitpid(child_pid, &status, 0), 1484 SyscallSucceedsWithValue(child_pid)); 1485 // Let's see that process exited normally. 1486 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 1487 << " status " << status; 1488 } 1489 #endif 1490 1491 TEST(PtraceTest, AttachingConvertsGroupStopToPtraceStop) { 1492 pid_t const child_pid = fork(); 1493 if (child_pid == 0) { 1494 // In child process. 1495 while (true) { 1496 pause(); 1497 } 1498 } 1499 // In parent process. 1500 ASSERT_THAT(child_pid, SyscallSucceeds()); 1501 1502 // SIGSTOP the child and wait for it to stop. 1503 ASSERT_THAT(kill(child_pid, SIGSTOP), SyscallSucceeds()); 1504 int status; 1505 ASSERT_THAT(waitpid(child_pid, &status, WUNTRACED), 1506 SyscallSucceedsWithValue(child_pid)); 1507 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 1508 << " status " << status; 1509 1510 // Attach to the child and expect it to re-enter a traced group-stop despite 1511 // already being stopped. 1512 ASSERT_THAT(ptrace(PTRACE_ATTACH, child_pid, 0, 0), SyscallSucceeds()); 1513 ASSERT_THAT(waitpid(child_pid, &status, 0), 1514 SyscallSucceedsWithValue(child_pid)); 1515 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 1516 << " status " << status; 1517 1518 // Verify that the child is ptrace-stopped by checking that it can receive 1519 // ptrace commands requiring a ptrace-stop. 1520 EXPECT_THAT(ptrace(PTRACE_SETOPTIONS, child_pid, 0, 0), SyscallSucceeds()); 1521 1522 // Group-stop is distinguished from signal-delivery-stop by PTRACE_GETSIGINFO 1523 // failing with EINVAL. 1524 siginfo_t siginfo = {}; 1525 EXPECT_THAT(ptrace(PTRACE_GETSIGINFO, child_pid, 0, &siginfo), 1526 SyscallFailsWithErrno(EINVAL)); 1527 1528 // Detach from the child and expect it to stay stopped without a notification. 1529 ASSERT_THAT(ptrace(PTRACE_DETACH, child_pid, 0, 0), SyscallSucceeds()); 1530 ASSERT_THAT(waitpid(child_pid, &status, WUNTRACED | WNOHANG), 1531 SyscallSucceedsWithValue(0)); 1532 1533 // Sending it SIGCONT should cause it to leave its stop. 1534 ASSERT_THAT(kill(child_pid, SIGCONT), SyscallSucceeds()); 1535 ASSERT_THAT(waitpid(child_pid, &status, WCONTINUED), 1536 SyscallSucceedsWithValue(child_pid)); 1537 EXPECT_TRUE(WIFCONTINUED(status)) << " status " << status; 1538 1539 // Clean up the child. 1540 ASSERT_THAT(kill(child_pid, SIGKILL), SyscallSucceeds()); 1541 ASSERT_THAT(waitpid(child_pid, &status, 0), 1542 SyscallSucceedsWithValue(child_pid)); 1543 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 1544 << " status " << status; 1545 } 1546 1547 // Fixture for tests parameterized by whether or not to use PTRACE_O_TRACEEXEC. 1548 class PtraceExecveTest : public ::testing::TestWithParam<bool> { 1549 protected: 1550 bool TraceExec() const { return GetParam(); } 1551 }; 1552 1553 TEST_P(PtraceExecveTest, Execve_GetRegs_PeekUser_SIGKILL_TraceClone_TraceExit) { 1554 ExecveArray const owned_child_argv = {"/proc/self/exe", 1555 "--ptrace_test_execve_child"}; 1556 char* const* const child_argv = owned_child_argv.get(); 1557 1558 pid_t const child_pid = fork(); 1559 if (child_pid == 0) { 1560 // In child process. The test relies on calling execve() in a non-leader 1561 // thread; pthread_create() isn't async-signal-safe, so the safest way to 1562 // do this is to execve() first, then enable tracing and run the expected 1563 // child process behavior in the new subprocess. 1564 execve(child_argv[0], child_argv, /* envp = */ nullptr); 1565 TEST_PCHECK_MSG(false, "Survived execve to test child"); 1566 } 1567 // In parent process. 1568 ASSERT_THAT(child_pid, SyscallSucceeds()); 1569 1570 // Wait for the child to send itself SIGSTOP and enter signal-delivery-stop. 1571 int status; 1572 ASSERT_THAT(waitpid(child_pid, &status, 0), 1573 SyscallSucceedsWithValue(child_pid)); 1574 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 1575 << " status " << status; 1576 1577 // Enable PTRACE_O_TRACECLONE so we can get the ID of the child's non-leader 1578 // thread, PTRACE_O_TRACEEXIT so we can observe the leader's death, and 1579 // PTRACE_O_TRACEEXEC if required by the test. (The leader doesn't call 1580 // execve, but options should be inherited across clone.) 1581 long opts = PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXIT; 1582 if (TraceExec()) { 1583 opts |= PTRACE_O_TRACEEXEC; 1584 } 1585 ASSERT_THAT(ptrace(PTRACE_SETOPTIONS, child_pid, 0, opts), SyscallSucceeds()); 1586 1587 // Suppress the SIGSTOP and wait for the child's leader thread to report 1588 // PTRACE_EVENT_CLONE. Get the new thread's ID from the event. 1589 ASSERT_THAT(ptrace(PTRACE_CONT, child_pid, 0, 0), SyscallSucceeds()); 1590 ASSERT_THAT(waitpid(child_pid, &status, 0), 1591 SyscallSucceedsWithValue(child_pid)); 1592 EXPECT_EQ(SIGTRAP | (PTRACE_EVENT_CLONE << 8), status >> 8); 1593 unsigned long eventmsg; 1594 ASSERT_THAT(ptrace(PTRACE_GETEVENTMSG, child_pid, 0, &eventmsg), 1595 SyscallSucceeds()); 1596 pid_t const nonleader_tid = eventmsg; 1597 pid_t const leader_tid = child_pid; 1598 1599 // The new thread should be ptraced and in signal-delivery-stop by SIGSTOP due 1600 // to PTRACE_O_TRACECLONE. 1601 // 1602 // Before bf959931ddb88c4e4366e96dd22e68fa0db9527c "wait/ptrace: assume __WALL 1603 // if the child is traced" (4.7) , waiting on it requires __WCLONE since, as a 1604 // non-leader, its termination signal is 0. After, a standard wait is 1605 // sufficient. 1606 ASSERT_THAT(waitpid(nonleader_tid, &status, __WCLONE), 1607 SyscallSucceedsWithValue(nonleader_tid)); 1608 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 1609 << " status " << status; 1610 1611 // Resume both child threads. 1612 for (pid_t const tid : {leader_tid, nonleader_tid}) { 1613 ASSERT_THAT(ptrace(PTRACE_CONT, tid, 0, 0), SyscallSucceeds()); 1614 } 1615 1616 // The non-leader child thread should call execve, causing the leader thread 1617 // to enter PTRACE_EVENT_EXIT with an apparent exit code of 0. At this point, 1618 // the leader has not yet exited, so the non-leader should be blocked in 1619 // execve. 1620 ASSERT_THAT(waitpid(leader_tid, &status, 0), 1621 SyscallSucceedsWithValue(leader_tid)); 1622 EXPECT_EQ(SIGTRAP | (PTRACE_EVENT_EXIT << 8), status >> 8); 1623 ASSERT_THAT(ptrace(PTRACE_GETEVENTMSG, leader_tid, 0, &eventmsg), 1624 SyscallSucceeds()); 1625 EXPECT_TRUE(WIFEXITED(eventmsg) && WEXITSTATUS(eventmsg) == 0) 1626 << " eventmsg " << eventmsg; 1627 EXPECT_THAT(waitpid(nonleader_tid, &status, __WCLONE | WNOHANG), 1628 SyscallSucceedsWithValue(0)); 1629 1630 // Allow the leader to continue exiting. This should allow the non-leader to 1631 // complete its execve, causing the original leader to be reaped without 1632 // further notice and the non-leader to steal its ID. 1633 ASSERT_THAT(ptrace(PTRACE_CONT, leader_tid, 0, 0), SyscallSucceeds()); 1634 ASSERT_THAT(waitpid(leader_tid, &status, 0), 1635 SyscallSucceedsWithValue(leader_tid)); 1636 if (TraceExec()) { 1637 // If PTRACE_O_TRACEEXEC was enabled, the execing thread should be in 1638 // PTRACE_EVENT_EXEC-stop, with the event message set to its old thread ID. 1639 EXPECT_EQ(SIGTRAP | (PTRACE_EVENT_EXEC << 8), status >> 8); 1640 ASSERT_THAT(ptrace(PTRACE_GETEVENTMSG, leader_tid, 0, &eventmsg), 1641 SyscallSucceeds()); 1642 EXPECT_EQ(nonleader_tid, eventmsg); 1643 } else { 1644 // Otherwise, the execing thread should have received SIGTRAP and should now 1645 // be in signal-delivery-stop. 1646 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) 1647 << " status " << status; 1648 } 1649 1650 #ifdef __x86_64__ 1651 { 1652 // CS should be 0x33, indicating an 64-bit binary. 1653 constexpr uint64_t kAMD64UserCS = 0x33; 1654 EXPECT_THAT(ptrace(PTRACE_PEEKUSER, leader_tid, 1655 offsetof(struct user_regs_struct, cs), 0), 1656 SyscallSucceedsWithValue(kAMD64UserCS)); 1657 struct user_regs_struct regs = {}; 1658 ASSERT_THAT(ptrace(PTRACE_GETREGS, leader_tid, 0, ®s), 1659 SyscallSucceeds()); 1660 EXPECT_EQ(kAMD64UserCS, regs.cs); 1661 } 1662 #endif // defined(__x86_64__) 1663 1664 // PTRACE_O_TRACEEXIT should have been inherited across execve. Send SIGKILL, 1665 // which should end the PTRACE_EVENT_EXEC-stop or signal-delivery-stop and 1666 // leave the child in PTRACE_EVENT_EXIT-stop. 1667 ASSERT_THAT(kill(leader_tid, SIGKILL), SyscallSucceeds()); 1668 ASSERT_THAT(waitpid(leader_tid, &status, 0), 1669 SyscallSucceedsWithValue(leader_tid)); 1670 EXPECT_EQ(SIGTRAP | (PTRACE_EVENT_EXIT << 8), status >> 8); 1671 ASSERT_THAT(ptrace(PTRACE_GETEVENTMSG, leader_tid, 0, &eventmsg), 1672 SyscallSucceeds()); 1673 EXPECT_TRUE(WIFSIGNALED(eventmsg) && WTERMSIG(eventmsg) == SIGKILL) 1674 << " eventmsg " << eventmsg; 1675 1676 // End the PTRACE_EVENT_EXIT stop, allowing the child to exit. 1677 ASSERT_THAT(ptrace(PTRACE_CONT, leader_tid, 0, 0), SyscallSucceeds()); 1678 ASSERT_THAT(waitpid(leader_tid, &status, 0), 1679 SyscallSucceedsWithValue(leader_tid)); 1680 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 1681 << " status " << status; 1682 } 1683 1684 [[noreturn]] void RunExecveChild() { 1685 // Enable tracing, then raise SIGSTOP and expect our parent to suppress it. 1686 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 1687 MaybeSave(); 1688 RaiseSignal(SIGSTOP); 1689 MaybeSave(); 1690 1691 // Call execve() in a non-leader thread. As long as execve() succeeds, what 1692 // exactly we execve() shouldn't really matter, since the tracer should kill 1693 // us after execve() completes. 1694 ScopedThread t([&] { 1695 ExecveArray const owned_child_argv = {"/proc/self/exe", 1696 "--this_flag_shouldnt_exist"}; 1697 char* const* const child_argv = owned_child_argv.get(); 1698 execve(child_argv[0], child_argv, /* envp = */ nullptr); 1699 TEST_PCHECK_MSG(false, "Survived execve? (thread)"); 1700 }); 1701 t.Join(); 1702 TEST_CHECK_MSG(false, "Survived execve? (main)"); 1703 _exit(1); 1704 } 1705 1706 INSTANTIATE_TEST_SUITE_P(TraceExec, PtraceExecveTest, ::testing::Bool()); 1707 1708 // This test has expectations on when syscall-enter/exit-stops occur that are 1709 // violated if saving occurs, since saving interrupts all syscalls, causing 1710 // premature syscall-exit. 1711 TEST(PtraceTest, ExitWhenParentIsNotTracer_Syscall_TraceVfork_TraceVforkDone) { 1712 constexpr int kExitTraceeExitCode = 99; 1713 1714 pid_t const child_pid = fork(); 1715 if (child_pid == 0) { 1716 // In child process. 1717 1718 // Block SIGCHLD so it doesn't interrupt wait4. 1719 sigset_t mask; 1720 TEST_PCHECK(sigemptyset(&mask) == 0); 1721 TEST_PCHECK(sigaddset(&mask, SIGCHLD) == 0); 1722 TEST_PCHECK(sigprocmask(SIG_SETMASK, &mask, nullptr) == 0); 1723 MaybeSave(); 1724 1725 // Enable tracing, then raise SIGSTOP and expect our parent to suppress it. 1726 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 1727 MaybeSave(); 1728 RaiseSignal(SIGSTOP); 1729 MaybeSave(); 1730 1731 // Spawn a vfork child that exits immediately, and reap it. Don't save 1732 // after vfork since the parent expects to see wait4 as the next syscall. 1733 pid_t const pid = vfork(); 1734 if (pid == 0) { 1735 _exit(kExitTraceeExitCode); 1736 } 1737 TEST_PCHECK_MSG(pid > 0, "vfork failed"); 1738 1739 int status; 1740 TEST_PCHECK(wait4(pid, &status, 0, nullptr) > 0); 1741 MaybeSave(); 1742 TEST_CHECK(WIFEXITED(status) && WEXITSTATUS(status) == kExitTraceeExitCode); 1743 _exit(0); 1744 } 1745 // In parent process. 1746 ASSERT_THAT(child_pid, SyscallSucceeds()); 1747 1748 // Wait for the child to send itself SIGSTOP and enter signal-delivery-stop. 1749 int status; 1750 ASSERT_THAT(child_pid, SyscallSucceeds()); 1751 ASSERT_THAT(waitpid(child_pid, &status, 0), 1752 SyscallSucceedsWithValue(child_pid)); 1753 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 1754 << " status " << status; 1755 1756 // Enable PTRACE_O_TRACEVFORK so we can get the ID of the grandchild, 1757 // PTRACE_O_TRACEVFORKDONE so we can observe PTRACE_EVENT_VFORK_DONE, and 1758 // PTRACE_O_TRACESYSGOOD so syscall-enter/exit-stops are unambiguously 1759 // indicated by a stop signal of SIGTRAP|0x80 rather than just SIGTRAP. 1760 ASSERT_THAT(ptrace(PTRACE_SETOPTIONS, child_pid, 0, 1761 PTRACE_O_TRACEVFORK | PTRACE_O_TRACEVFORKDONE | 1762 PTRACE_O_TRACESYSGOOD), 1763 SyscallSucceeds()); 1764 1765 // Suppress the SIGSTOP and wait for the child to report PTRACE_EVENT_VFORK. 1766 // Get the new process' ID from the event. 1767 ASSERT_THAT(ptrace(PTRACE_CONT, child_pid, 0, 0), SyscallSucceeds()); 1768 ASSERT_THAT(waitpid(child_pid, &status, 0), 1769 SyscallSucceedsWithValue(child_pid)); 1770 EXPECT_EQ(SIGTRAP | (PTRACE_EVENT_VFORK << 8), status >> 8); 1771 unsigned long eventmsg; 1772 ASSERT_THAT(ptrace(PTRACE_GETEVENTMSG, child_pid, 0, &eventmsg), 1773 SyscallSucceeds()); 1774 pid_t const grandchild_pid = eventmsg; 1775 1776 // The grandchild should be traced by us and in signal-delivery-stop by 1777 // SIGSTOP due to PTRACE_O_TRACEVFORK. This allows us to wait on it even 1778 // though we're not its parent. 1779 ASSERT_THAT(waitpid(grandchild_pid, &status, 0), 1780 SyscallSucceedsWithValue(grandchild_pid)); 1781 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 1782 << " status " << status; 1783 1784 // Resume the child with PTRACE_SYSCALL. Since the grandchild is still in 1785 // signal-delivery-stop, the child should remain in vfork() waiting for the 1786 // grandchild to exec or exit. 1787 ASSERT_THAT(ptrace(PTRACE_SYSCALL, child_pid, 0, 0), SyscallSucceeds()); 1788 absl::SleepFor(absl::Seconds(1)); 1789 ASSERT_THAT(waitpid(child_pid, &status, WNOHANG), 1790 SyscallSucceedsWithValue(0)); 1791 1792 // Suppress the grandchild's SIGSTOP and wait for the grandchild to exit. Pass 1793 // WNOWAIT to waitid() so that we don't acknowledge the grandchild's exit yet. 1794 ASSERT_THAT(ptrace(PTRACE_CONT, grandchild_pid, 0, 0), SyscallSucceeds()); 1795 siginfo_t siginfo = {}; 1796 ASSERT_THAT(waitid(P_PID, grandchild_pid, &siginfo, WEXITED | WNOWAIT), 1797 SyscallSucceeds()); 1798 EXPECT_EQ(SIGCHLD, siginfo.si_signo); 1799 EXPECT_EQ(CLD_EXITED, siginfo.si_code); 1800 EXPECT_EQ(kExitTraceeExitCode, siginfo.si_status); 1801 EXPECT_EQ(grandchild_pid, siginfo.si_pid); 1802 EXPECT_EQ(getuid(), siginfo.si_uid); 1803 1804 // The child should now be in PTRACE_EVENT_VFORK_DONE stop. The event 1805 // message should still be the grandchild's PID. 1806 ASSERT_THAT(waitpid(child_pid, &status, 0), 1807 SyscallSucceedsWithValue(child_pid)); 1808 EXPECT_EQ(SIGTRAP | (PTRACE_EVENT_VFORK_DONE << 8), status >> 8); 1809 ASSERT_THAT(ptrace(PTRACE_GETEVENTMSG, child_pid, 0, &eventmsg), 1810 SyscallSucceeds()); 1811 EXPECT_EQ(grandchild_pid, eventmsg); 1812 1813 // Resume the child with PTRACE_SYSCALL again and expect it to enter 1814 // syscall-exit-stop for vfork() or clone(), either of which should return the 1815 // grandchild's PID from the syscall. Aside from PTRACE_O_TRACESYSGOOD, 1816 // syscall-stops are distinguished from signal-delivery-stop by 1817 // PTRACE_GETSIGINFO returning a siginfo for which si_code == SIGTRAP or 1818 // SIGTRAP|0x80. 1819 ASSERT_THAT(ptrace(PTRACE_SYSCALL, child_pid, 0, 0), SyscallSucceeds()); 1820 ASSERT_THAT(waitpid(child_pid, &status, 0), 1821 SyscallSucceedsWithValue(child_pid)); 1822 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80)) 1823 << " status " << status; 1824 ASSERT_THAT(ptrace(PTRACE_GETSIGINFO, child_pid, 0, &siginfo), 1825 SyscallSucceeds()); 1826 EXPECT_TRUE(siginfo.si_code == SIGTRAP || siginfo.si_code == (SIGTRAP | 0x80)) 1827 << "si_code = " << siginfo.si_code; 1828 1829 { 1830 struct user_regs_struct regs = {}; 1831 struct iovec iov; 1832 iov.iov_base = ®s; 1833 iov.iov_len = sizeof(regs); 1834 EXPECT_THAT(ptrace(PTRACE_GETREGSET, child_pid, NT_PRSTATUS, &iov), 1835 SyscallSucceeds()); 1836 #if defined(__x86_64__) 1837 EXPECT_TRUE(regs.orig_rax == SYS_vfork || regs.orig_rax == SYS_clone) 1838 << "orig_rax = " << regs.orig_rax; 1839 EXPECT_EQ(grandchild_pid, regs.rax); 1840 #elif defined(__aarch64__) 1841 EXPECT_TRUE(regs.regs[8] == SYS_clone) << "regs[8] = " << regs.regs[8]; 1842 EXPECT_EQ(grandchild_pid, regs.regs[0]); 1843 #endif // defined(__x86_64__) 1844 } 1845 1846 // After this point, the child will be making wait4 syscalls that will be 1847 // interrupted by saving, so saving is not permitted. Note that this is 1848 // explicitly released below once the grandchild exits. 1849 DisableSave ds; 1850 1851 // Resume the child with PTRACE_SYSCALL again and expect it to enter 1852 // syscall-enter-stop for wait4(). 1853 ASSERT_THAT(ptrace(PTRACE_SYSCALL, child_pid, 0, 0), SyscallSucceeds()); 1854 ASSERT_THAT(waitpid(child_pid, &status, 0), 1855 SyscallSucceedsWithValue(child_pid)); 1856 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80)) 1857 << " status " << status; 1858 ASSERT_THAT(ptrace(PTRACE_GETSIGINFO, child_pid, 0, &siginfo), 1859 SyscallSucceeds()); 1860 EXPECT_TRUE(siginfo.si_code == SIGTRAP || siginfo.si_code == (SIGTRAP | 0x80)) 1861 << "si_code = " << siginfo.si_code; 1862 #ifdef __x86_64__ 1863 { 1864 EXPECT_THAT(ptrace(PTRACE_PEEKUSER, child_pid, 1865 offsetof(struct user_regs_struct, orig_rax), 0), 1866 SyscallSucceedsWithValue(SYS_wait4)); 1867 } 1868 #endif // defined(__x86_64__) 1869 1870 // Resume the child with PTRACE_SYSCALL again. Since the grandchild is 1871 // waiting for the tracer (us) to acknowledge its exit first, wait4 should 1872 // block. 1873 ASSERT_THAT(ptrace(PTRACE_SYSCALL, child_pid, 0, 0), SyscallSucceeds()); 1874 absl::SleepFor(absl::Seconds(1)); 1875 ASSERT_THAT(waitpid(child_pid, &status, WNOHANG), 1876 SyscallSucceedsWithValue(0)); 1877 1878 // Acknowledge the grandchild's exit. 1879 ASSERT_THAT(waitpid(grandchild_pid, &status, 0), 1880 SyscallSucceedsWithValue(grandchild_pid)); 1881 ds.reset(); 1882 1883 // Now the child should enter syscall-exit-stop for wait4, returning with the 1884 // grandchild's PID. 1885 ASSERT_THAT(waitpid(child_pid, &status, 0), 1886 SyscallSucceedsWithValue(child_pid)); 1887 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80)) 1888 << " status " << status; 1889 { 1890 struct user_regs_struct regs = {}; 1891 struct iovec iov; 1892 iov.iov_base = ®s; 1893 iov.iov_len = sizeof(regs); 1894 EXPECT_THAT(ptrace(PTRACE_GETREGSET, child_pid, NT_PRSTATUS, &iov), 1895 SyscallSucceeds()); 1896 #if defined(__x86_64__) 1897 EXPECT_EQ(SYS_wait4, regs.orig_rax); 1898 EXPECT_EQ(grandchild_pid, regs.rax); 1899 #elif defined(__aarch64__) 1900 EXPECT_EQ(SYS_wait4, regs.regs[8]); 1901 EXPECT_EQ(grandchild_pid, regs.regs[0]); 1902 #endif // defined(__x86_64__) 1903 } 1904 1905 // Detach from the child and wait for it to exit. 1906 ASSERT_THAT(ptrace(PTRACE_DETACH, child_pid, 0, 0), SyscallSucceeds()); 1907 ASSERT_THAT(waitpid(child_pid, &status, 0), 1908 SyscallSucceedsWithValue(child_pid)); 1909 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 1910 << " status " << status; 1911 } 1912 1913 // These tests requires knowledge of architecture-specific syscall convention. 1914 #ifdef __x86_64__ 1915 TEST(PtraceTest, Int3) { 1916 SKIP_IF(PlatformSupportInt3() == PlatformSupport::NotSupported); 1917 1918 pid_t const child_pid = fork(); 1919 if (child_pid == 0) { 1920 // In child process. 1921 1922 // Enable tracing. 1923 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 1924 1925 // Interrupt 3 - trap to debugger 1926 asm("int3"); 1927 1928 _exit(56); 1929 } 1930 // In parent process. 1931 ASSERT_THAT(child_pid, SyscallSucceeds()); 1932 1933 int status; 1934 ASSERT_THAT(waitpid(child_pid, &status, 0), 1935 SyscallSucceedsWithValue(child_pid)); 1936 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) 1937 << " status " << status; 1938 1939 ASSERT_THAT(ptrace(PTRACE_CONT, child_pid, 0, 0), SyscallSucceeds()); 1940 1941 // The child should validate the injected return value and then exit normally. 1942 ASSERT_THAT(waitpid(child_pid, &status, 0), 1943 SyscallSucceedsWithValue(child_pid)); 1944 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 56) 1945 << " status " << status; 1946 } 1947 1948 TEST(PtraceTest, Sysemu_PokeUser) { 1949 constexpr int kSysemuHelperFirstExitCode = 126; 1950 constexpr uint64_t kSysemuInjectedExitGroupReturn = 42; 1951 1952 pid_t const child_pid = fork(); 1953 if (child_pid == 0) { 1954 // In child process. 1955 1956 // Enable tracing, then raise SIGSTOP and expect our parent to suppress it. 1957 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 1958 RaiseSignal(SIGSTOP); 1959 1960 // Try to exit_group, expecting the tracer to skip the syscall and set its 1961 // own return value. 1962 int const rv = syscall(SYS_exit_group, kSysemuHelperFirstExitCode); 1963 TEST_PCHECK_MSG(rv == kSysemuInjectedExitGroupReturn, 1964 "exit_group returned incorrect value"); 1965 1966 _exit(0); 1967 } 1968 // In parent process. 1969 ASSERT_THAT(child_pid, SyscallSucceeds()); 1970 1971 // Wait for the child to send itself SIGSTOP and enter signal-delivery-stop. 1972 int status; 1973 ASSERT_THAT(waitpid(child_pid, &status, 0), 1974 SyscallSucceedsWithValue(child_pid)); 1975 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 1976 << " status " << status; 1977 1978 // Suppress the SIGSTOP and wait for the child to enter syscall-enter-stop 1979 // for its first exit_group syscall. 1980 ASSERT_THAT(ptrace(kPtraceSysemu, child_pid, 0, 0), SyscallSucceeds()); 1981 ASSERT_THAT(waitpid(child_pid, &status, 0), 1982 SyscallSucceedsWithValue(child_pid)); 1983 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) 1984 << " status " << status; 1985 1986 struct user_regs_struct regs = {}; 1987 ASSERT_THAT(ptrace(PTRACE_GETREGS, child_pid, 0, ®s), SyscallSucceeds()); 1988 EXPECT_EQ(SYS_exit_group, regs.orig_rax); 1989 EXPECT_EQ(-ENOSYS, regs.rax); 1990 EXPECT_EQ(kSysemuHelperFirstExitCode, regs.rdi); 1991 1992 // Replace the exit_group return value, then resume the child, which should 1993 // automatically skip the syscall. 1994 ASSERT_THAT( 1995 ptrace(PTRACE_POKEUSER, child_pid, offsetof(struct user_regs_struct, rax), 1996 kSysemuInjectedExitGroupReturn), 1997 SyscallSucceeds()); 1998 ASSERT_THAT(ptrace(PTRACE_DETACH, child_pid, 0, 0), SyscallSucceeds()); 1999 2000 // The child should validate the injected return value and then exit normally. 2001 ASSERT_THAT(waitpid(child_pid, &status, 0), 2002 SyscallSucceedsWithValue(child_pid)); 2003 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 2004 << " status " << status; 2005 } 2006 2007 // This test also cares about syscall-exit-stop. 2008 TEST(PtraceTest, ERESTART) { 2009 constexpr int kSigno = SIGUSR1; 2010 2011 pid_t const child_pid = fork(); 2012 if (child_pid == 0) { 2013 // In child process. 2014 2015 // Ignore, but unblock, kSigno. 2016 struct sigaction sa = {}; 2017 sa.sa_handler = SIG_IGN; 2018 TEST_PCHECK(sigfillset(&sa.sa_mask) == 0); 2019 TEST_PCHECK(sigaction(kSigno, &sa, nullptr) == 0); 2020 MaybeSave(); 2021 TEST_PCHECK(sigprocmask(SIG_UNBLOCK, &sa.sa_mask, nullptr) == 0); 2022 MaybeSave(); 2023 2024 // Enable tracing, then raise SIGSTOP and expect our parent to suppress it. 2025 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 2026 RaiseSignal(SIGSTOP); 2027 2028 // Invoke the pause syscall, which normally should not return until we 2029 // receive a signal that "either terminates the process or causes the 2030 // invocation of a signal-catching function". 2031 pause(); 2032 2033 _exit(0); 2034 } 2035 ASSERT_THAT(child_pid, SyscallSucceeds()); 2036 2037 // Wait for the child to send itself SIGSTOP and enter signal-delivery-stop. 2038 int status; 2039 ASSERT_THAT(waitpid(child_pid, &status, 0), 2040 SyscallSucceedsWithValue(child_pid)); 2041 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 2042 << " status " << status; 2043 2044 // After this point, the child's pause syscall will be interrupted by saving, 2045 // so saving is not permitted. Note that this is explicitly released below 2046 // once the child is stopped. 2047 DisableSave ds; 2048 2049 // Suppress the SIGSTOP and wait for the child to enter syscall-enter-stop for 2050 // its pause syscall. 2051 ASSERT_THAT(ptrace(PTRACE_SYSCALL, child_pid, 0, 0), SyscallSucceeds()); 2052 ASSERT_THAT(waitpid(child_pid, &status, 0), 2053 SyscallSucceedsWithValue(child_pid)); 2054 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) 2055 << " status " << status; 2056 2057 struct user_regs_struct regs = {}; 2058 ASSERT_THAT(ptrace(PTRACE_GETREGS, child_pid, 0, ®s), SyscallSucceeds()); 2059 EXPECT_EQ(SYS_pause, regs.orig_rax); 2060 EXPECT_EQ(-ENOSYS, regs.rax); 2061 2062 // Resume the child with PTRACE_SYSCALL and expect it to block in the pause 2063 // syscall. 2064 ASSERT_THAT(ptrace(PTRACE_SYSCALL, child_pid, 0, 0), SyscallSucceeds()); 2065 absl::SleepFor(absl::Seconds(1)); 2066 ASSERT_THAT(waitpid(child_pid, &status, WNOHANG), 2067 SyscallSucceedsWithValue(0)); 2068 2069 // Send the child kSigno, causing it to return ERESTARTNOHAND and enter 2070 // syscall-exit-stop from the pause syscall. 2071 constexpr int ERESTARTNOHAND = 514; 2072 ASSERT_THAT(kill(child_pid, kSigno), SyscallSucceeds()); 2073 ASSERT_THAT(waitpid(child_pid, &status, 0), 2074 SyscallSucceedsWithValue(child_pid)); 2075 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) 2076 << " status " << status; 2077 ds.reset(); 2078 2079 ASSERT_THAT(ptrace(PTRACE_GETREGS, child_pid, 0, ®s), SyscallSucceeds()); 2080 EXPECT_EQ(SYS_pause, regs.orig_rax); 2081 EXPECT_EQ(-ERESTARTNOHAND, regs.rax); 2082 2083 // Replace the return value from pause with 0, causing pause to not be 2084 // restarted despite kSigno being ignored. 2085 ASSERT_THAT(ptrace(PTRACE_POKEUSER, child_pid, 2086 offsetof(struct user_regs_struct, rax), 0), 2087 SyscallSucceeds()); 2088 2089 // Detach from the child and wait for it to exit. 2090 ASSERT_THAT(ptrace(PTRACE_DETACH, child_pid, 0, 0), SyscallSucceeds()); 2091 ASSERT_THAT(waitpid(child_pid, &status, 0), 2092 SyscallSucceedsWithValue(child_pid)); 2093 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 2094 << " status " << status; 2095 } 2096 #endif // defined(__x86_64__) 2097 2098 TEST(PtraceTest, Seize_Interrupt_Listen) { 2099 volatile long child_should_spin = 1; 2100 pid_t const child_pid = fork(); 2101 if (child_pid == 0) { 2102 // In child process. 2103 while (child_should_spin) { 2104 SleepSafe(absl::Seconds(1)); 2105 } 2106 _exit(1); 2107 } 2108 2109 // In parent process. 2110 ASSERT_THAT(child_pid, SyscallSucceeds()); 2111 2112 // Attach to the child with PTRACE_SEIZE; doing so should not stop the child. 2113 ASSERT_THAT(ptrace(PTRACE_SEIZE, child_pid, 0, 0), SyscallSucceeds()); 2114 int status; 2115 EXPECT_THAT(waitpid(child_pid, &status, WNOHANG), 2116 SyscallSucceedsWithValue(0)); 2117 2118 // Stop the child with PTRACE_INTERRUPT. 2119 ASSERT_THAT(ptrace(PTRACE_INTERRUPT, child_pid, 0, 0), SyscallSucceeds()); 2120 ASSERT_THAT(waitpid(child_pid, &status, 0), 2121 SyscallSucceedsWithValue(child_pid)); 2122 EXPECT_EQ(SIGTRAP | (kPtraceEventStop << 8), status >> 8); 2123 2124 // Unset child_should_spin to verify that the child never leaves the spin 2125 // loop. 2126 ASSERT_THAT(ptrace(PTRACE_POKEDATA, child_pid, &child_should_spin, 0), 2127 SyscallSucceeds()); 2128 2129 // Send SIGSTOP to the child, then resume it, allowing it to proceed to 2130 // signal-delivery-stop. 2131 ASSERT_THAT(kill(child_pid, SIGSTOP), SyscallSucceeds()); 2132 ASSERT_THAT(ptrace(PTRACE_CONT, child_pid, 0, 0), SyscallSucceeds()); 2133 ASSERT_THAT(waitpid(child_pid, &status, 0), 2134 SyscallSucceedsWithValue(child_pid)); 2135 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 2136 << " status " << status; 2137 2138 // Release the child from signal-delivery-stop without suppressing the 2139 // SIGSTOP, causing it to enter group-stop. 2140 ASSERT_THAT(ptrace(PTRACE_CONT, child_pid, 0, SIGSTOP), SyscallSucceeds()); 2141 ASSERT_THAT(waitpid(child_pid, &status, 0), 2142 SyscallSucceedsWithValue(child_pid)); 2143 EXPECT_EQ(SIGSTOP | (kPtraceEventStop << 8), status >> 8); 2144 2145 // "The state of the tracee after PTRACE_LISTEN is somewhat of a gray area: it 2146 // is not in any ptrace-stop (ptrace commands won't work on it, and it will 2147 // deliver waitpid(2) notifications), but it also may be considered 'stopped' 2148 // because it is not executing instructions (is not scheduled), and if it was 2149 // in group-stop before PTRACE_LISTEN, it will not respond to signals until 2150 // SIGCONT is received." - ptrace(2). 2151 ASSERT_THAT(ptrace(PTRACE_LISTEN, child_pid, 0, 0), SyscallSucceeds()); 2152 EXPECT_THAT(ptrace(PTRACE_CONT, child_pid, 0, 0), 2153 SyscallFailsWithErrno(ESRCH)); 2154 EXPECT_THAT(waitpid(child_pid, &status, WNOHANG), 2155 SyscallSucceedsWithValue(0)); 2156 EXPECT_THAT(kill(child_pid, SIGTERM), SyscallSucceeds()); 2157 absl::SleepFor(absl::Seconds(1)); 2158 EXPECT_THAT(waitpid(child_pid, &status, WNOHANG), 2159 SyscallSucceedsWithValue(0)); 2160 2161 // Send SIGCONT to the child, causing it to leave group-stop and re-trap due 2162 // to PTRACE_LISTEN. 2163 EXPECT_THAT(kill(child_pid, SIGCONT), SyscallSucceeds()); 2164 ASSERT_THAT(waitpid(child_pid, &status, 0), 2165 SyscallSucceedsWithValue(child_pid)); 2166 EXPECT_EQ(SIGTRAP | (kPtraceEventStop << 8), status >> 8); 2167 2168 // Detach the child and expect it to exit due to the SIGTERM we sent while 2169 // it was stopped by PTRACE_LISTEN. 2170 ASSERT_THAT(ptrace(PTRACE_DETACH, child_pid, 0, 0), SyscallSucceeds()); 2171 ASSERT_THAT(waitpid(child_pid, &status, 0), 2172 SyscallSucceedsWithValue(child_pid)); 2173 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM) 2174 << " status " << status; 2175 } 2176 2177 TEST(PtraceTest, Interrupt_Listen_RequireSeize) { 2178 pid_t const child_pid = fork(); 2179 if (child_pid == 0) { 2180 // In child process. 2181 TEST_PCHECK(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); 2182 MaybeSave(); 2183 raise(SIGSTOP); 2184 _exit(0); 2185 } 2186 // In parent process. 2187 ASSERT_THAT(child_pid, SyscallSucceeds()); 2188 2189 // Wait for the child to send itself SIGSTOP and enter signal-delivery-stop. 2190 int status; 2191 ASSERT_THAT(waitpid(child_pid, &status, 0), 2192 SyscallSucceedsWithValue(child_pid)); 2193 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) 2194 << " status " << status; 2195 2196 // PTRACE_INTERRUPT and PTRACE_LISTEN should fail since the child wasn't 2197 // attached with PTRACE_SEIZE, leaving the child in signal-delivery-stop. 2198 EXPECT_THAT(ptrace(PTRACE_INTERRUPT, child_pid, 0, 0), 2199 SyscallFailsWithErrno(EIO)); 2200 EXPECT_THAT(ptrace(PTRACE_LISTEN, child_pid, 0, 0), 2201 SyscallFailsWithErrno(EIO)); 2202 2203 // Suppress SIGSTOP and detach from the child, expecting it to exit normally. 2204 ASSERT_THAT(ptrace(PTRACE_DETACH, child_pid, 0, 0), SyscallSucceeds()); 2205 ASSERT_THAT(waitpid(child_pid, &status, 0), 2206 SyscallSucceedsWithValue(child_pid)); 2207 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 2208 << " status " << status; 2209 } 2210 2211 TEST(PtraceTest, SeizeSetOptions) { 2212 pid_t const child_pid = fork(); 2213 if (child_pid == 0) { 2214 // In child process. 2215 while (true) { 2216 SleepSafe(absl::Seconds(1)); 2217 } 2218 } 2219 2220 // In parent process. 2221 ASSERT_THAT(child_pid, SyscallSucceeds()); 2222 2223 // Attach to the child with PTRACE_SEIZE while setting PTRACE_O_TRACESYSGOOD. 2224 ASSERT_THAT(ptrace(PTRACE_SEIZE, child_pid, 0, PTRACE_O_TRACESYSGOOD), 2225 SyscallSucceeds()); 2226 2227 // Stop the child with PTRACE_INTERRUPT. 2228 ASSERT_THAT(ptrace(PTRACE_INTERRUPT, child_pid, 0, 0), SyscallSucceeds()); 2229 int status; 2230 ASSERT_THAT(waitpid(child_pid, &status, 0), 2231 SyscallSucceedsWithValue(child_pid)); 2232 EXPECT_EQ(SIGTRAP | (kPtraceEventStop << 8), status >> 8); 2233 2234 // Resume the child with PTRACE_SYSCALL and wait for it to enter 2235 // syscall-enter-stop. The stop signal status from the syscall stop should be 2236 // SIGTRAP|0x80, reflecting PTRACE_O_TRACESYSGOOD. 2237 ASSERT_THAT(ptrace(PTRACE_SYSCALL, child_pid, 0, 0), SyscallSucceeds()); 2238 ASSERT_THAT(waitpid(child_pid, &status, 0), 2239 SyscallSucceedsWithValue(child_pid)); 2240 EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80)) 2241 << " status " << status; 2242 2243 // Clean up the child. 2244 ASSERT_THAT(kill(child_pid, SIGKILL), SyscallSucceeds()); 2245 ASSERT_THAT(waitpid(child_pid, &status, 0), 2246 SyscallSucceedsWithValue(child_pid)); 2247 if (WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80)) { 2248 // "SIGKILL kills even within system calls (syscall-exit-stop is not 2249 // generated prior to death by SIGKILL). The net effect is that SIGKILL 2250 // always kills the process (all its threads), even if some threads of the 2251 // process are ptraced." - ptrace(2). This is technically true, but... 2252 // 2253 // When we send SIGKILL to the child, kernel/signal.c:complete_signal() => 2254 // signal_wake_up(resume=1) kicks the tracee out of the syscall-enter-stop. 2255 // The pending SIGKILL causes the syscall to be skipped, but the child 2256 // thread still reports syscall-exit before checking for pending signals; in 2257 // current kernels, this is 2258 // arch/x86/entry/common.c:syscall_return_slowpath() => 2259 // syscall_slow_exit_work() => 2260 // include/linux/tracehook.h:tracehook_report_syscall_exit() => 2261 // ptrace_report_syscall() => kernel/signal.c:ptrace_notify() => 2262 // ptrace_do_notify() => ptrace_stop(). 2263 // 2264 // ptrace_stop() sets the task's state to TASK_TRACED and the task's 2265 // exit_code to SIGTRAP|0x80 (passed by ptrace_report_syscall()), then calls 2266 // freezable_schedule(). freezable_schedule() eventually reaches 2267 // __schedule(), which detects signal_pending_state() due to the pending 2268 // SIGKILL, sets the task's state back to TASK_RUNNING, and returns without 2269 // descheduling. Thus, the task never enters syscall-exit-stop. However, if 2270 // our wait4() => kernel/exit.c:wait_task_stopped() racily observes the 2271 // TASK_TRACED state and the non-zero exit code set by ptrace_stop() before 2272 // __schedule() sets the state back to TASK_RUNNING, it will return the 2273 // task's exit_code as status W_STOPCODE(SIGTRAP|0x80). So we get a spurious 2274 // syscall-exit-stop notification, and need to wait4() again for task exit. 2275 // 2276 // gVisor is not susceptible to this race because 2277 // kernel.Task.waitCollectTraceeStopLocked() checks specifically for an 2278 // active ptraceStop, which is not initiated if SIGKILL is pending. 2279 std::cout << "Observed syscall-exit after SIGKILL" << std::endl; 2280 ASSERT_THAT(waitpid(child_pid, &status, 0), 2281 SyscallSucceedsWithValue(child_pid)); 2282 } 2283 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) 2284 << " status " << status; 2285 } 2286 2287 TEST(PtraceTest, SetYAMAPtraceScope) { 2288 // Do not modify the ptrace scope on the host. 2289 SKIP_IF(!IsRunningOnGvisor()); 2290 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN))); 2291 2292 const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE( 2293 Open(std::string(kYamaPtraceScopePath), O_RDWR)); 2294 2295 ASSERT_THAT(write(fd.get(), "0", 1), SyscallSucceedsWithValue(1)); 2296 2297 ASSERT_THAT(lseek(fd.get(), 0, SEEK_SET), SyscallSucceeds()); 2298 std::vector<char> buf(10); 2299 EXPECT_THAT(read(fd.get(), buf.data(), buf.size()), SyscallSucceeds()); 2300 EXPECT_STREQ(buf.data(), "0\n"); 2301 2302 // Test that a child can attach to its parent when ptrace_scope is 0. 2303 AutoCapability cap(CAP_SYS_PTRACE, false); 2304 pid_t const child_pid = fork(); 2305 if (child_pid == 0) { 2306 TEST_PCHECK(CheckPtraceAttach(getppid()) == 0); 2307 _exit(0); 2308 } 2309 ASSERT_THAT(child_pid, SyscallSucceeds()); 2310 2311 int status; 2312 ASSERT_THAT(waitpid(child_pid, &status, 0), SyscallSucceeds()); 2313 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 2314 << " status " << status; 2315 2316 // Set ptrace_scope back to 1 (and try writing with a newline). 2317 ASSERT_THAT(lseek(fd.get(), 0, SEEK_SET), SyscallSucceeds()); 2318 ASSERT_THAT(write(fd.get(), "1\n", 2), SyscallSucceedsWithValue(2)); 2319 2320 ASSERT_THAT(lseek(fd.get(), 0, SEEK_SET), SyscallSucceeds()); 2321 EXPECT_THAT(read(fd.get(), buf.data(), buf.size()), SyscallSucceeds()); 2322 EXPECT_STREQ(buf.data(), "1\n"); 2323 } 2324 2325 } // namespace 2326 2327 } // namespace testing 2328 } // namespace gvisor 2329 2330 int main(int argc, char** argv) { 2331 gvisor::testing::TestInit(&argc, &argv); 2332 2333 if (absl::GetFlag(FLAGS_ptrace_test_execve_child)) { 2334 gvisor::testing::RunExecveChild(); 2335 } 2336 2337 int fd = absl::GetFlag(FLAGS_ptrace_test_fd); 2338 2339 if (absl::GetFlag(FLAGS_ptrace_test_trace_descendants_allowed)) { 2340 gvisor::testing::RunTraceDescendantsAllowed(fd); 2341 } 2342 2343 if (absl::GetFlag(FLAGS_ptrace_test_ptrace_attacher)) { 2344 gvisor::testing::RunPtraceAttacher(fd); 2345 } 2346 2347 if (absl::GetFlag(FLAGS_ptrace_test_prctl_set_ptracer)) { 2348 gvisor::testing::RunPrctlSetPtracer(fd); 2349 } 2350 2351 if (absl::GetFlag( 2352 FLAGS_ptrace_test_prctl_set_ptracer_and_exit_tracee_thread)) { 2353 gvisor::testing::RunPrctlSetPtracerPersistsPastTraceeThreadExit(fd); 2354 } 2355 2356 if (absl::GetFlag(FLAGS_ptrace_test_prctl_set_ptracer_and_exec_non_leader)) { 2357 gvisor::testing::RunPrctlSetPtracerDoesNotPersistPastNonLeaderExec( 2358 fd); 2359 } 2360 2361 if (absl::GetFlag( 2362 FLAGS_ptrace_test_prctl_set_ptracer_and_exit_tracer_thread)) { 2363 gvisor::testing::RunPrctlSetPtracerDoesNotPersistPastTracerThreadExit( 2364 absl::GetFlag( 2365 FLAGS_ptrace_test_prctl_set_ptracer_and_exit_tracer_thread_tid), 2366 fd); 2367 } 2368 2369 if (absl::GetFlag( 2370 FLAGS_ptrace_test_prctl_set_ptracer_respects_tracer_thread_id)) { 2371 gvisor::testing::RunPrctlSetPtracerRespectsTracerThreadID( 2372 absl::GetFlag( 2373 FLAGS_ptrace_test_prctl_set_ptracer_respects_tracer_thread_id_tid), 2374 fd); 2375 } 2376 2377 if (absl::GetFlag(FLAGS_ptrace_test_tracee)) { 2378 gvisor::testing::RunTracee(fd); 2379 } 2380 2381 int pid = absl::GetFlag(FLAGS_ptrace_test_trace_tid); 2382 if (pid != -1) { 2383 gvisor::testing::RunTraceTID(pid, fd); 2384 } 2385 2386 return gvisor::testing::RunAllTests(); 2387 }