summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJamie Liu <jamieliu@google.com>2019-04-02 18:12:11 -0700
committerShentubot <shentubot@google.com>2019-04-02 18:13:19 -0700
commitc4caccd54042ea80a6e8b5a8f5ce59ee87a7f424 (patch)
tree1e4fba0db9c622267fbe76e2393909922b9521e5
parent5c465603b67285f04d0b7a38e1bc185b29b4085e (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.go2
-rw-r--r--test/syscalls/linux/ptrace.cc40
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