From 0146b318371360bda1f0efdd196d42417287e41c Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Fri, 24 Sep 2021 00:11:14 +0900 Subject: [PATCH] ptrace: Allow separate tracing of signals and syscalls --- base/usr/include/kernel/process.h | 4 +++- base/usr/include/sys/ptrace.h | 3 ++- kernel/sys/ptrace.c | 14 ++++++++++++-- kernel/sys/signal.c | 2 +- kernel/sys/syscall.c | 4 ++-- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/base/usr/include/kernel/process.h b/base/usr/include/kernel/process.h index 3265c2e2..d57829b5 100644 --- a/base/usr/include/kernel/process.h +++ b/base/usr/include/kernel/process.h @@ -67,7 +67,9 @@ typedef struct file_descriptors { #define PROC_FLAG_RUNNING 0x08 #define PROC_FLAG_SLEEP_INT 0x10 #define PROC_FLAG_SUSPENDED 0x20 -#define PROC_FLAG_TRACED 0x40 + +#define PROC_FLAG_TRACE_SYSCALLS 0x40 +#define PROC_FLAG_TRACE_SIGNALS 0x80 typedef struct process { pid_t id; /* PID */ diff --git a/base/usr/include/sys/ptrace.h b/base/usr/include/sys/ptrace.h index 60fe6da1..bffa1ffb 100644 --- a/base/usr/include/sys/ptrace.h +++ b/base/usr/include/sys/ptrace.h @@ -11,7 +11,8 @@ enum __ptrace_request { PTRACE_DETACH, PTRACE_TRACEME, PTRACE_GETREGS, - PTRACE_PEEKDATA + PTRACE_PEEKDATA, + PTRACE_SIGNALS_ONLY_PLZ }; enum __ptrace_event { diff --git a/kernel/sys/ptrace.c b/kernel/sys/ptrace.c index 0cb0852c..542d5315 100644 --- a/kernel/sys/ptrace.c +++ b/kernel/sys/ptrace.c @@ -16,7 +16,7 @@ long ptrace_attach(pid_t pid) { process_t * tracee = process_from_pid(pid); if (!tracee) return -ESRCH; if (this_core->current_process->user != 0 && this_core->current_process->user != tracee->user) return -EPERM; - __sync_or_and_fetch(&tracee->flags, PROC_FLAG_TRACED); + __sync_or_and_fetch(&tracee->flags, (PROC_FLAG_TRACE_SYSCALLS | PROC_FLAG_TRACE_SIGNALS)); tracee->tracer = this_core->current_process->id; send_signal(pid, SIGSTOP, 1); return 0; @@ -26,7 +26,7 @@ long ptrace_self(void) { process_t * parent = process_get_parent((process_t*)this_core->current_process); if (!parent) return -EINVAL; - __sync_or_and_fetch(&this_core->current_process->flags, PROC_FLAG_TRACED); + __sync_or_and_fetch(&this_core->current_process->flags, (PROC_FLAG_TRACE_SYSCALLS | PROC_FLAG_TRACE_SIGNALS)); this_core->current_process->tracer = parent->id; return 0; @@ -95,6 +95,14 @@ long ptrace_peek(pid_t pid, void * addr, void * data) { return 0; } +long ptrace_signals_only(pid_t pid) { + process_t * tracee = process_from_pid(pid); + if (!tracee || (tracee->tracer != this_core->current_process->id) || !(tracee->flags & PROC_FLAG_SUSPENDED)) return -ESRCH; + __sync_and_and_fetch(&tracee->flags, ~(PROC_FLAG_TRACE_SYSCALLS)); + return 0; +} + + long ptrace_handle(long request, pid_t pid, void * addr, void * data) { switch (request) { case PTRACE_ATTACH: @@ -107,6 +115,8 @@ long ptrace_handle(long request, pid_t pid, void * addr, void * data) { return ptrace_continue(pid,(uintptr_t)data); case PTRACE_PEEKDATA: return ptrace_peek(pid,addr,data); + case PTRACE_SIGNALS_ONLY_PLZ: + return ptrace_signals_only(pid); default: return -EINVAL; } diff --git a/kernel/sys/signal.c b/kernel/sys/signal.c index f72a3ef1..0ada653d 100644 --- a/kernel/sys/signal.c +++ b/kernel/sys/signal.c @@ -78,7 +78,7 @@ void handle_signal(process_t * proc, signal_t * sig) { free(sig); /* Are we being traced? */ - if (this_core->current_process->flags & PROC_FLAG_TRACED) { + if (this_core->current_process->flags & PROC_FLAG_TRACE_SIGNALS) { signum = ptrace_signal(signum, 0); } diff --git a/kernel/sys/syscall.c b/kernel/sys/syscall.c index 0c4d1e87..195be8f7 100644 --- a/kernel/sys/syscall.c +++ b/kernel/sys/syscall.c @@ -1138,7 +1138,7 @@ void syscall_handler(struct regs * r) { scall_func func = syscalls[arch_syscall_number(r)]; this_core->current_process->syscall_registers = r; - if (this_core->current_process->flags & PROC_FLAG_TRACED) { + if (this_core->current_process->flags & PROC_FLAG_TRACE_SYSCALLS) { ptrace_signal(SIGTRAP, PTRACE_EVENT_SYSCALL_ENTER); } @@ -1146,7 +1146,7 @@ void syscall_handler(struct regs * r) { arch_syscall_arg0(r), arch_syscall_arg1(r), arch_syscall_arg2(r), arch_syscall_arg3(r), arch_syscall_arg4(r))); - if (this_core->current_process->flags & PROC_FLAG_TRACED) { + if (this_core->current_process->flags & PROC_FLAG_TRACE_SYSCALLS) { ptrace_signal(SIGTRAP, PTRACE_EVENT_SYSCALL_EXIT); } }