- Change ptrace_getsiginfo() to use ptrace_rw_siginfo(). - Fix the semantics. We should return EINVAL only if the tracee was stopped. If it didn't report the signal, we fill siginfo like ptrace_notify() did.
Note! Currently do_ptrace_notify_stop() clears context->ev_code for debugging purposes, this means info->si_code is not right currently. --- kernel/ptrace.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) --- PU/kernel/ptrace.c~63_GET_SIGINFO 2009-10-03 02:49:42.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-03 03:19:47.000000000 +0200 @@ -801,22 +801,23 @@ static int ptrace_rw_siginfo(struct task return err; } -static int ptrace_getsiginfo(struct utrace_engine *engine, - struct task_struct *child, siginfo_t *info) +static int ptrace_getsiginfo(struct ptrace_context *context, + struct task_struct *tracee, siginfo_t *info) { - unsigned long flags; - int error = -ESRCH; + /* jctl stop ? */ + if (!ev_pending(context)) + return -EINVAL; - if (lock_task_sighand(child, &flags)) { - error = -EINVAL; - if (likely(ptrace_context(engine)->siginfo != NULL)) { - *info = *ptrace_context(engine)->siginfo; - error = 0; - } - unlock_task_sighand(child, &flags); - } + if (context->siginfo) + return ptrace_rw_siginfo(tracee, context, info, false); - return error; + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = context->ev_code; // XXX: ev_code was already cleared!!! + info->si_pid = task_pid_vnr(tracee); + info->si_uid = task_uid(tracee); + + return 0; } static int ptrace_setsiginfo(struct utrace_engine *engine, @@ -1045,7 +1046,8 @@ int ptrace_request(struct task_struct *c break; case PTRACE_GETSIGINFO: - ret = ptrace_getsiginfo(engine, child, &siginfo); + ret = ptrace_getsiginfo(ptrace_context(engine), + child, &siginfo); if (!ret) ret = copy_siginfo_to_user((siginfo_t __user *) data, &siginfo); @@ -1214,7 +1216,8 @@ int compat_ptrace_request(struct task_st break; case PTRACE_GETSIGINFO: - ret = ptrace_getsiginfo(engine, child, &siginfo); + ret = ptrace_getsiginfo(ptrace_context(engine), + child, &siginfo); if (!ret) ret = copy_siginfo_to_user32( (struct compat_siginfo __user *) datap,