support PTRACE_SYSCALL.

support PTRACE_O_TRACESYSGOOD.
ptrace_report_exec() calls ptrace_report_signal().

refs #265
This commit is contained in:
Susumu Komae
2015-02-17 16:56:27 +09:00
committed by postpeta
parent 8568a73f33
commit fa15f6b106
4 changed files with 47 additions and 45 deletions

View File

@@ -391,7 +391,7 @@ void set_single_step(struct process *proc)
extern void coredump(struct process *proc, void *regs); extern void coredump(struct process *proc, void *regs);
static void ptrace_report_signal(struct process *proc, struct x86_regs *regs, int sig) void ptrace_report_signal(struct process *proc, int sig)
{ {
long rc; long rc;
@@ -401,6 +401,7 @@ static void ptrace_report_signal(struct process *proc, struct x86_regs *regs, in
proc->ftn->exit_status = sig; proc->ftn->exit_status = sig;
/* Transition process state */ /* Transition process state */
proc->ftn->status = PS_TRACED; proc->ftn->status = PS_TRACED;
proc->ftn->ptrace &= ~PT_TRACE_SYSCALL_MASK;
ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock); ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
if (proc->ftn->parent) { if (proc->ftn->parent) {
/* kill SIGCHLD */ /* kill SIGCHLD */
@@ -525,7 +526,7 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
case SIGTTIN: case SIGTTIN:
case SIGTTOU: case SIGTTOU:
if(ptraceflag){ if(ptraceflag){
ptrace_report_signal(proc, regs, orgsig); ptrace_report_signal(proc, orgsig);
} }
else{ else{
dkprintf("do_signal,SIGSTOP,changing state\n"); dkprintf("do_signal,SIGSTOP,changing state\n");

View File

@@ -62,6 +62,9 @@
#define PT_TRACED 0x80 /* The process is ptraced */ #define PT_TRACED 0x80 /* The process is ptraced */
#define PT_TRACE_EXEC 0x100 /* Trace execve(2) */ #define PT_TRACE_EXEC 0x100 /* Trace execve(2) */
#define PT_TRACE_SYSCALL_ENTER 0x200 /* Trace syscall enter */
#define PT_TRACE_SYSCALL_EXIT 0x400 /* Trace syscall exit */
#define PT_TRACE_SYSCALL_MASK (PT_TRACE_SYSCALL_ENTER | PT_TRACE_SYSCALL_EXIT)
#define PTRACE_TRACEME 0 #define PTRACE_TRACEME 0
#define PTRACE_PEEKTEXT 1 #define PTRACE_PEEKTEXT 1

View File

@@ -387,7 +387,6 @@ int ptrace_traceme(void){
} }
clear_single_step(proc); clear_single_step(proc);
/* TODO: other flags may reset */
out: out:
dkprintf("ptrace_traceme,returning,error=%d\n", error); dkprintf("ptrace_traceme,returning,error=%d\n", error);

View File

@@ -1433,53 +1433,42 @@ SYSCALL_DECLARE(arch_prctl)
ihk_mc_syscall_arg1(ctx)); ihk_mc_syscall_arg1(ctx));
} }
extern void ptrace_report_signal(struct process *proc, int sig);
static int ptrace_report_exec(struct process *proc) static int ptrace_report_exec(struct process *proc)
{ {
dkprintf("ptrace_report_exec,enter\n"); int ptrace = proc->ftn->ptrace;
int error = 0;
long rc;
struct siginfo info;
if (!(proc->ftn->ptrace & (PT_TRACE_EXEC|PTRACE_O_TRACEEXEC))) { if (ptrace & (PT_TRACE_EXEC|PTRACE_O_TRACEEXEC)) {
goto out; int sig = (SIGTRAP | (PTRACE_EVENT_EXEC << 8));
ptrace_report_signal(proc, sig);
} }
return 0;
}
/* Save reason why stopped and process state for wait4() to reap */
ihk_mc_spinlock_lock_noirq(&proc->ftn->lock);
proc->ftn->exit_status = (SIGTRAP | (PTRACE_EVENT_EXEC << 8));
/* Transition process state */
proc->ftn->status = PS_TRACED;
ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
dkprintf("ptrace_report_exec,kill SIGCHLD\n"); static void ptrace_syscall_enter(struct process *proc)
if (proc->ftn->parent) { {
/* kill SIGCHLD */ int ptrace = proc->ftn->ptrace;
ihk_mc_spinlock_lock_noirq(&proc->ftn->parent->lock);
if (proc->ftn->parent->owner) { if (ptrace & PT_TRACE_SYSCALL_ENTER) {
memset(&info, '\0', sizeof info); int sig = (SIGTRAP | ((ptrace & PTRACE_O_TRACESYSGOOD) ? 0x80 : 0));
info.si_signo = SIGCHLD; ptrace_report_signal(proc, sig);
info.si_code = CLD_TRAPPED; ihk_mc_spinlock_lock_noirq(&proc->ftn->lock);
info._sifields._sigchld.si_pid = proc->ftn->pid; if (proc->ftn->ptrace & PT_TRACE_SYSCALL_ENTER) {
info._sifields._sigchld.si_status = proc->ftn->exit_status; proc->ftn->ptrace |= PT_TRACE_SYSCALL_EXIT;
rc = do_kill(proc->ftn->parent->pid, -1, SIGCHLD, &info, 0);
if(rc < 0) {
dkprintf("ptrace_report_exec,do_kill failed\n");
}
} }
ihk_mc_spinlock_unlock_noirq(&proc->ftn->parent->lock); ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
/* Wake parent (if sleeping in wait4()) */
waitq_wakeup(&proc->ftn->parent->waitpid_q);
} }
}
/* Sleep */ static void ptrace_syscall_exit(struct process *proc)
dkprintf("ptrace_report_exec,sleeping\n"); {
int ptrace = proc->ftn->ptrace;
schedule();
dkprintf("ptrace_report_exec,woken up\n");
out: if (ptrace & PT_TRACE_SYSCALL_EXIT) {
return error; int sig = (SIGTRAP | ((ptrace & PTRACE_O_TRACESYSGOOD) ? 0x80 : 0));
ptrace_report_signal(proc, sig);
}
} }
static int ptrace_check_clone_event(struct process *proc, int clone_flags) static int ptrace_check_clone_event(struct process *proc, int clone_flags)
@@ -1522,6 +1511,7 @@ static int ptrace_report_clone(struct process *proc, struct process *new, int ev
/* Transition process state */ /* Transition process state */
proc->ftn->status = PS_TRACED; proc->ftn->status = PS_TRACED;
proc->ftn->ptrace_eventmsg = new->ftn->pid; proc->ftn->ptrace_eventmsg = new->ftn->pid;
proc->ftn->ptrace &= ~PT_TRACE_SYSCALL_MASK;
ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock); ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
dkprintf("ptrace_report_clone,kill SIGCHLD\n"); dkprintf("ptrace_report_clone,kill SIGCHLD\n");
@@ -2613,9 +2603,12 @@ static int ptrace_wakeup_sig(int pid, long request, long data) {
if (request == PTRACE_SINGLESTEP) { if (request == PTRACE_SINGLESTEP) {
set_single_step(child); set_single_step(child);
} }
ihk_mc_spinlock_lock_noirq(&child->ftn->lock);
child->ftn->ptrace &= ~PT_TRACE_SYSCALL_MASK;
if (request == PTRACE_SYSCALL) { if (request == PTRACE_SYSCALL) {
/* TODO: may set PTRACE_SYSCALL flag */ child->ftn->ptrace |= PT_TRACE_SYSCALL_ENTER;
} }
ihk_mc_spinlock_unlock_noirq(&child->ftn->lock);
if(data != 0 && data != SIGSTOP) { if(data != 0 && data != SIGSTOP) {
struct process *proc; struct process *proc;
@@ -2908,8 +2901,7 @@ static int ptrace_attach(int pid)
} }
} }
proc->uctx->rflags &= ~RFLAGS_TF; /* SingleStep clear */ clear_single_step(proc);
/* TODO: other flags may reset */
memset(&info, '\0', sizeof info); memset(&info, '\0', sizeof info);
info.si_signo = SIGSTOP; info.si_signo = SIGSTOP;
@@ -2991,7 +2983,6 @@ found:
} }
clear_single_step(proc); clear_single_step(proc);
/* TODO: other flags may clear */
if (data != 0) { if (data != 0) {
memset(&info, '\0', sizeof info); memset(&info, '\0', sizeof info);
@@ -3117,7 +3108,8 @@ SYSCALL_DECLARE(ptrace)
dkprintf("ptrace: unimplemented ptrace(PTRACE_GETFPXREGS) called.\n"); dkprintf("ptrace: unimplemented ptrace(PTRACE_GETFPXREGS) called.\n");
break; break;
case PTRACE_SYSCALL: case PTRACE_SYSCALL:
dkprintf("ptrace: unimplemented ptrace(PTRACE_SYSCALL) called.\n"); dkprintf("ptrace: PTRACE_SYSCALL: data=%d\n", data);
error = ptrace_wakeup_sig(pid, request, data);
break; break;
case PTRACE_GETSIGINFO: case PTRACE_GETSIGINFO:
dkprintf("ptrace: unimplemented ptrace(PTRACE_GETSIGINFO) called.\n"); dkprintf("ptrace: unimplemented ptrace(PTRACE_GETSIGINFO) called.\n");
@@ -4037,6 +4029,9 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
cpu_enable_interrupt(); cpu_enable_interrupt();
if (cpu_local_var(current)->ftn->ptrace) {
ptrace_syscall_enter(cpu_local_var(current));
}
#if 0 #if 0
if(num != 24) // if not sched_yield if(num != 24) // if not sched_yield
@@ -4083,6 +4078,10 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
check_signal(l, NULL); check_signal(l, NULL);
check_need_resched(); check_need_resched();
if (cpu_local_var(current)->ftn->ptrace) {
ptrace_syscall_exit(cpu_local_var(current));
}
return l; return l;
} }