diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 4f01c8a3..9824a9db 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -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) { diff --git a/kernel/include/process.h b/kernel/include/process.h index cb632de3..e9c9f9e0 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -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 */ diff --git a/kernel/syscall.c b/kernel/syscall.c index e677e3f0..fa5715b6 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -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();