diff options
author | Jamie Liu <jamieliu@google.com> | 2019-04-02 18:12:11 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-04-02 18:13:19 -0700 |
commit | c4caccd54042ea80a6e8b5a8f5ce59ee87a7f424 (patch) | |
tree | 1e4fba0db9c622267fbe76e2393909922b9521e5 | |
parent | 5c465603b67285f04d0b7a38e1bc185b29b4085e (diff) |
Set options on the correct Task in PTRACE_SEIZE.
$ docker run --rm --runtime=runsc -it --cap-add=SYS_PTRACE debian bash -c "apt-get update && apt-get install strace && strace ls"
...
Setting up strace (4.15-2) ...
execve("/bin/ls", ["ls"], [/* 6 vars */]) = 0
brk(NULL) = 0x5646d8c1e000
uname({sysname="Linux", nodename="114ef93d2db3", ...}) = 0
...
PiperOrigin-RevId: 241643321
Change-Id: Ie4bce27a7fb147eef07bbae5895c6ef3f529e177
-rw-r--r-- | pkg/sentry/kernel/ptrace.go | 2 | ||||
-rw-r--r-- | test/syscalls/linux/ptrace.cc | 40 |
2 files changed, 41 insertions, 1 deletions
diff --git a/pkg/sentry/kernel/ptrace.go b/pkg/sentry/kernel/ptrace.go index e8043bf8a..8d78b2fb3 100644 --- a/pkg/sentry/kernel/ptrace.go +++ b/pkg/sentry/kernel/ptrace.go @@ -374,7 +374,7 @@ func (t *Task) ptraceAttach(target *Task, seize bool, opts uintptr) error { return syserror.EPERM } if seize { - if err := t.ptraceSetOptionsLocked(opts); err != nil { + if err := target.ptraceSetOptionsLocked(opts); err != nil { return syserror.EIO } } diff --git a/test/syscalls/linux/ptrace.cc b/test/syscalls/linux/ptrace.cc index 6d5c425d8..8fc0045ce 100644 --- a/test/syscalls/linux/ptrace.cc +++ b/test/syscalls/linux/ptrace.cc @@ -1120,6 +1120,46 @@ TEST(PtraceTest, Interrupt_Listen_RequireSeize) { << " status " << status; } +TEST(PtraceTest, SeizeSetOptions) { + pid_t const child_pid = fork(); + if (child_pid == 0) { + // In child process. + while (true) { + SleepSafe(absl::Seconds(1)); + } + } + + // In parent process. + ASSERT_THAT(child_pid, SyscallSucceeds()); + + // Attach to the child with PTRACE_SEIZE while setting PTRACE_O_TRACESYSGOOD. + ASSERT_THAT(ptrace(PTRACE_SEIZE, child_pid, 0, PTRACE_O_TRACESYSGOOD), + SyscallSucceeds()); + + // Stop the child with PTRACE_INTERRUPT. + ASSERT_THAT(ptrace(PTRACE_INTERRUPT, child_pid, 0, 0), SyscallSucceeds()); + int status; + ASSERT_THAT(waitpid(child_pid, &status, 0), + SyscallSucceedsWithValue(child_pid)); + EXPECT_EQ(SIGTRAP | (kPtraceEventStop << 8), status >> 8); + + // Resume the child with PTRACE_SYSCALL and wait for it to enter + // syscall-enter-stop. The stop signal status from the syscall stop should be + // SIGTRAP|0x80, reflecting PTRACE_O_TRACESYSGOOD. + ASSERT_THAT(ptrace(PTRACE_SYSCALL, child_pid, 0, 0), SyscallSucceeds()); + ASSERT_THAT(waitpid(child_pid, &status, 0), + SyscallSucceedsWithValue(child_pid)); + EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80)) + << " status " << status; + + // SIGKILL the child (detaching the tracer) and wait for it to exit. + ASSERT_THAT(kill(child_pid, SIGKILL), SyscallSucceeds()); + ASSERT_THAT(waitpid(child_pid, &status, 0), + SyscallSucceedsWithValue(child_pid)); + EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) + << " status " << status; +} + } // namespace } // namespace testing |