ptrace: Allow separate tracing of signals and syscalls

This commit is contained in:
K. Lange 2021-09-24 00:11:14 +09:00
parent 8859849452
commit 0146b31837
5 changed files with 20 additions and 7 deletions

View File

@ -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 */

View File

@ -11,7 +11,8 @@ enum __ptrace_request {
PTRACE_DETACH,
PTRACE_TRACEME,
PTRACE_GETREGS,
PTRACE_PEEKDATA
PTRACE_PEEKDATA,
PTRACE_SIGNALS_ONLY_PLZ
};
enum __ptrace_event {

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}
}