The parting signal must not be visible to the next attacher.
Compatibility!

Change ptrace_detach_task() to set context->resume = UTRACE_DETACH and
do utrace_control(UTRACE_RESUME) in case the tracee should process the
signal.

If the tracee is killed we don't care what will happen. Otherwise it
ptrace_report_signal(UTRACE_SIGNAL_REPORT) must be called, it will
return UTRACE_DETACH and complete the detach.

TODO:

        - re-check UTRACE_SIGNAL_HANDLER is not possible

        - info->si_pid will be wrong if sig != si_signo.
          how can we fix this? can't we ignore the problem?
          upstream is buggy too, I hope we can

        - the next attach is not possible until the tracee
          does ptrace_report_signal(). Fixed by the next
          patches.

---

 kernel/ptrace.c |   21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

--- PU/kernel/ptrace.c~75_DETACHED_ENGINE       2009-10-09 16:49:32.000000000 
+0200
+++ PU/kernel/ptrace.c  2009-10-09 17:14:30.000000000 +0200
@@ -87,9 +87,12 @@ static struct utrace_engine *ptrace_look
                                        &ptrace_utrace_ops, NULL);
 }
 
-static void detach_signal(struct task_struct *tracee,
+static enum utrace_resume_action
+detach_signal(struct task_struct *tracee,
                                struct ptrace_context *context, int sig)
 {
+       enum utrace_resume_action action = UTRACE_DETACH;
+
        switch (get_stop_event(context)) {
        case PTRACE_EVENT_SYSCALL_ENTRY:
        case PTRACE_EVENT_SYSCALL_EXIT:
@@ -98,26 +101,30 @@ static void detach_signal(struct task_st
                break;
 
        case PTRACE_EVENT_SIGNAL:
-               if (!valid_signal(sig))
-                       sig = context->signr;
-               if (sig)
-                       send_sig_info(sig, SEND_SIG_PRIV, tracee);
+               if (valid_signal(sig))
+                       context->signr = sig;
+               context->stop_code = 0;
+               context->resume = UTRACE_DETACH;
+               action = UTRACE_RESUME;
                break;
        }
+
+       return action;
 }
 
 static void ptrace_detach_task(struct task_struct *child, int sig)
 {
        struct utrace_engine *engine = ptrace_lookup_engine(child);
+       enum utrace_resume_action action = UTRACE_DETACH;
        int ret;
 
        if (unlikely(IS_ERR(engine)))
                return;
 
        if (sig)
-               detach_signal(child, ptrace_context(engine), sig);
+               action = detach_signal(child, ptrace_context(engine), sig);
 
-       ret = utrace_control(child, engine, UTRACE_DETACH);
+       ret = utrace_control(child, engine, action);
        WARN_ON(ret && ret != -EINPROGRESS &&
                ret != -ESRCH && ret != -EALREADY);
 

Reply via email to