Introduce detach_signal(sig) helper. It is called by ptrace_detach_task()
instead of removed ptrace_do_detach()->send_sig().

!valid_signal(sig) means that the tracer exits and detaches implicitly.

If sig == 0 - nothing to do, just detach and return. If the tracee
reported the signal, it will be cancelled.

If sig != 0, the tracee should process the reported signal. Currently
we call send_sig_info().

Also, handle PTRACE_EVENT_SYSCALL_XXX case.

---

 kernel/ptrace.c |   28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

--- PU/kernel/ptrace.c~74_DETACH_SIGNAL 2009-10-09 16:48:40.000000000 +0200
+++ PU/kernel/ptrace.c  2009-10-09 16:49:32.000000000 +0200
@@ -87,6 +87,25 @@ static struct utrace_engine *ptrace_look
                                        &ptrace_utrace_ops, NULL);
 }
 
+static void detach_signal(struct task_struct *tracee,
+                               struct ptrace_context *context, int sig)
+{
+       switch (get_stop_event(context)) {
+       case PTRACE_EVENT_SYSCALL_ENTRY:
+       case PTRACE_EVENT_SYSCALL_EXIT:
+               if (valid_signal(sig))
+                       send_sig_info(sig, SEND_SIG_PRIV, tracee);
+               break;
+
+       case PTRACE_EVENT_SIGNAL:
+               if (!valid_signal(sig))
+                       sig = context->signr;
+               if (sig)
+                       send_sig_info(sig, SEND_SIG_PRIV, tracee);
+               break;
+       }
+}
+
 static void ptrace_detach_task(struct task_struct *child, int sig)
 {
        struct utrace_engine *engine = ptrace_lookup_engine(child);
@@ -95,6 +114,9 @@ static void ptrace_detach_task(struct ta
        if (unlikely(IS_ERR(engine)))
                return;
 
+       if (sig)
+               detach_signal(child, ptrace_context(engine), sig);
+
        ret = utrace_control(child, engine, UTRACE_DETACH);
        WARN_ON(ret && ret != -EINPROGRESS &&
                ret != -ESRCH && ret != -EALREADY);
@@ -676,12 +698,8 @@ static void ptrace_do_detach(struct task
         */
        detach = tracee->ptrace != 0;
        release = false;
-       if (likely(detach)) {
-               // XXX: temporary hack
-               if (data && valid_signal(data))
-                       send_sig(data, tracee, 1);
+       if (likely(detach))
                release = __ptrace_detach(current, tracee);
-       }
        write_unlock_irq(&tasklist_lock);
 
        if (unlikely(release))

Reply via email to