diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index 5d7d61d5..d4662f7e 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -506,7 +506,16 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin int coredumped = 0; siginfo_t info; - kfree(pending); + if(ptraceflag){ + if(proc->ptrace_recvsig) + kfree(proc->ptrace_recvsig); + proc->ptrace_recvsig = pending; + if(proc->ptrace_sendsig) + kfree(proc->ptrace_sendsig); + proc->ptrace_sendsig = NULL; + } + else + kfree(pending); ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate); switch (sig) { case SIGSTOP: diff --git a/kernel/include/process.h b/kernel/include/process.h index c21cd006..79edaf9c 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -386,6 +386,8 @@ struct process { unsigned long saved_auxv[AUXV_LEN]; unsigned long *ptrace_debugreg; /* debug registers for ptrace */ + struct sig_pending *ptrace_recvsig; + struct sig_pending *ptrace_sendsig; }; struct process_vm { diff --git a/kernel/process.c b/kernel/process.c index cfb7ff74..e7edb98e 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -1969,6 +1969,12 @@ void destroy_process(struct process *proc) if (proc->ptrace_debugreg) { kfree(proc->ptrace_debugreg); } + if (proc->ptrace_recvsig) { + kfree(proc->ptrace_recvsig); + } + if (proc->ptrace_sendsig) { + kfree(proc->ptrace_sendsig); + } ihk_mc_free_pages(proc, KERNEL_STACK_NR_PAGES); } diff --git a/kernel/syscall.c b/kernel/syscall.c index bb5466f9..1ce3f055 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -2715,11 +2715,18 @@ static int ptrace_wakeup_sig(int pid, long request, long data) { /* TODO: Tracing process replace the original signal with "data" */ - proc = cpu_local_var(current); - memset(&info, '\0', sizeof info); - info.si_signo = data; - info.si_code = SI_USER; - info._sifields._kill.si_pid = proc->ftn->pid; + if (request == PTRACE_CONT && child->ptrace_sendsig) { + memcpy(&info, &child->ptrace_sendsig->info, sizeof info); + kfree(child->ptrace_sendsig); + child->ptrace_sendsig = NULL; + } + else { + proc = cpu_local_var(current); + memset(&info, '\0', sizeof info); + info.si_signo = data; + info.si_code = SI_USER; + info._sifields._kill.si_pid = proc->ftn->pid; + } error = do_kill(pid, -1, data, &info, 1); if (error < 0) { goto out; @@ -3185,6 +3192,70 @@ static long ptrace_geteventmsg(int pid, long data) return rc; } +static long +ptrace_getsiginfo(int pid, siginfo_t *data) +{ + ihk_spinlock_t *savelock; + unsigned long irqstate; + struct process *child; + struct process *proc = cpu_local_var(current); + int rc = 0; + + child = findthread_and_lock(pid, -1, &savelock, &irqstate); + if (!child) { + return -ESRCH; + } + + if (child->ftn->status != PS_TRACED) { + rc = -ESRCH; + } + else if (child->ptrace_recvsig) { + if (copy_to_user(proc, data, &child->ptrace_recvsig->info, sizeof(siginfo_t))) { + rc = -EFAULT; + } + } + else { + rc = -ESRCH; + } + ihk_mc_spinlock_unlock(savelock, irqstate); + return rc; +} + +static long +ptrace_setsiginfo(int pid, siginfo_t *data) +{ + ihk_spinlock_t *savelock; + unsigned long irqstate; + struct process *child; + struct process *proc = cpu_local_var(current); + int rc = 0; + +kprintf("ptrace_setsiginfo: sig=%d errno=%d code=%d\n", data->si_signo, data->si_errno, data->si_code); + child = findthread_and_lock(pid, -1, &savelock, &irqstate); + if (!child) { + return -ESRCH; + } + + if (child->ftn->status != PS_TRACED) { + rc = -ESRCH; + } + else { + if (child->ptrace_sendsig == NULL) { + child->ptrace_sendsig = kmalloc(sizeof(struct sig_pending), IHK_MC_AP_NOWAIT); + if (child->ptrace_sendsig == NULL) { + rc = -ENOMEM; + } + } + + if (!rc && + copy_from_user(proc, &child->ptrace_sendsig->info, data, sizeof(siginfo_t))) { + rc = -EFAULT; + } + } + ihk_mc_spinlock_unlock(savelock, irqstate); + return rc; +} + SYSCALL_DECLARE(ptrace) { const long request = (long)ihk_mc_syscall_arg0(ctx); @@ -3269,9 +3340,11 @@ SYSCALL_DECLARE(ptrace) break; case PTRACE_GETSIGINFO: dkprintf("ptrace: unimplemented ptrace(PTRACE_GETSIGINFO) called.\n"); + error = ptrace_getsiginfo(pid, (siginfo_t *)data); break; case PTRACE_SETSIGINFO: dkprintf("ptrace: unimplemented ptrace(PTRACE_SETSIGINFO) called.\n"); + error = ptrace_setsiginfo(pid, (siginfo_t *)data); break; case PTRACE_GETREGSET: dkprintf("ptrace: unimplemented ptrace(PTRACE_GETREGSET) called.\n");