ptrace: fix execve and return value handling (fixes strace on aarch64)

Change-Id: Icb5cb7f7e99fdb74a8628bc6b550688df5fb056b
This commit is contained in:
Balazs Gerofi
2020-02-10 03:44:43 +00:00
parent 597baf8445
commit 4bbdee395e
3 changed files with 26 additions and 11 deletions

View File

@@ -964,6 +964,7 @@ void ptrace_report_signal(struct thread *thread, int sig)
/* save thread_info, if called by ptrace_report_exec() */
if (sig == ((SIGTRAP | (PTRACE_EVENT_EXEC << 8)))) {
memcpy(&tinfo, thread->ctx.thread, sizeof(struct thread_info));
thread->uctx->user_regs.regs[0] = 0;
}
mcs_rwlock_writer_lock(&proc->update_lock, &lock);
@@ -976,6 +977,13 @@ void ptrace_report_signal(struct thread *thread, int sig)
thread->exit_status = sig;
thread->status = PS_TRACED;
thread->ptrace &= ~PT_TRACE_SYSCALL;
if (sig == ((SIGTRAP | (PTRACE_EVENT_EXEC << 8))) &&
thread->ptrace & PTRACE_O_TRACEEXEC) {
/* PTRACE_O_TRACEEXEC: since Linux 3.0, the former
* thread ID can be retrieved with PTRACE_GETEVENTMSG.
* Report no change. */
thread->ptrace_eventmsg = thread->tid;
}
save_debugreg(thread->ptrace_debugreg);
if (sig == SIGSTOP || sig == SIGTSTP ||
sig == SIGTTIN || sig == SIGTTOU) {

View File

@@ -80,6 +80,7 @@
#define PT_TRACED 0x80 /* The process is ptraced */
#define PT_TRACE_EXEC 0x100 /* Trace execve(2) */
#define PT_TRACE_SYSCALL 0x200 /* Trace syscall enter */
#define PT_TRACED_AFTER_EXEC 0x1000
// ptrace(2) request
#define PTRACE_TRACEME 0
@@ -127,6 +128,7 @@
#define PTRACE_EVENT_EXEC 4
#define PTRACE_EVENT_VFORK_DONE 5
#define PTRACE_EVENT_EXIT 6
#define PTRACE_EVENT_SECCOMP 7
#define NT_X86_XSTATE 0x202 /* x86 XSAVE extended state */

View File

@@ -2312,6 +2312,7 @@ static int ptrace_report_exec(struct thread *thread)
ptrace_report_signal(thread, sig);
preempt_disable();
memcpy(&thread->ctx, &ctx, sizeof ctx);
thread->ptrace |= PT_TRACED_AFTER_EXEC;
}
return 0;
}
@@ -2593,10 +2594,6 @@ static int do_execveat(ihk_mc_user_context_t *ctx, int dirfd,
goto end;
}
if (thread->ptrace) {
arch_ptrace_syscall_event(thread, ctx, 0);
}
/* Unmap all memory areas of the process, userspace will be gone */
munmap_all();
@@ -6826,7 +6823,8 @@ static int ptrace_setoptions(int pid, int flags)
PTRACE_O_TRACEVFORK|
PTRACE_O_TRACECLONE|
PTRACE_O_TRACEEXEC|
PTRACE_O_TRACEVFORKDONE)) {
PTRACE_O_TRACEVFORKDONE|
PTRACE_O_TRACEEXIT)) {
kprintf("ptrace_setoptions: not supported flag %x\n", flags);
ret = -EINVAL;
goto out;
@@ -10005,8 +10003,17 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
cpu_enable_interrupt();
if (cpu_local_var(current)->ptrace) {
/*
* XXX: After PTRACE_EVENT_EXEC we need to report an extra SIGTRAP.
* This is a tmp fix and should be moved into ptrace_report_exec()
*/
if (cpu_local_var(current)->ptrace & PT_TRACED_AFTER_EXEC) {
arch_ptrace_syscall_event(cpu_local_var(current), ctx, 0);
cpu_local_var(current)->ptrace &= ~(PT_TRACED_AFTER_EXEC);
}
arch_ptrace_syscall_event(cpu_local_var(current),
ctx, -ENOSYS);
ctx, -ENOSYS);
num = ihk_mc_syscall_number(ctx);
}
@@ -10051,6 +10058,9 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
l = syscall_generic_forwarding(num, ctx);
}
/* Store return value so that PTRACE_GETREGSET will see it */
save_syscall_return_value(num, l);
if (cpu_local_var(current)->ptrace) {
/* arm64: The return value modified by the tracer is
* stored to x0 in the following check_signal().
@@ -10058,11 +10068,6 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
l = arch_ptrace_syscall_event(cpu_local_var(current), ctx, l);
}
/* x86_64: Setting l to rax is done in the
* following return.
*/
save_syscall_return_value(num, l);
#ifdef PROFILE_ENABLE
{
unsigned long ts = rdtsc();