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
This commit is contained in:
Jamie Liu
2019-04-02 18:13:19 -07:00
committed by Shentubot
parent 5c465603b6
commit c4caccd540
2 changed files with 41 additions and 1 deletions
+1 -1
View File
@@ -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
}
}
+40
View File
@@ -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