Change ptrace_report_clone() to do all attach work itself. Note that this
allows to greatly simplify do_fork() path wrt tracehooks. For example we
do not need tracehook_prepare_clone() at all. tracehook_finish_clone()
does not need tasklist. copy_process() does not need "int traced".

Both ptrace_report_clone() and ptrace_clone_attach() need more work.
ptrace_clone_attach() will be changed once we add engine->data.

---

 include/linux/ptrace.h    |    4 ---
 include/linux/tracehook.h |    8 ------
 kernel/ptrace.c           |   56 ++++++++++++++++++++++++++++------------------
 3 files changed, 35 insertions(+), 33 deletions(-)

--- PU/include/linux/ptrace.h~10_CLONE_ATTACH   2009-08-19 18:05:15.000000000 
+0200
+++ PU/include/linux/ptrace.h   2009-08-19 18:05:34.000000000 +0200
@@ -147,10 +147,6 @@ static inline void ptrace_init_task(stru
        INIT_LIST_HEAD(&child->ptraced);
        child->parent = child->real_parent;
        child->ptrace = 0;
-       if (unlikely(ptrace)) {
-               child->ptrace = current->ptrace;
-               ptrace_link(child, current->parent);
-       }
 }
 
 /**
--- PU/include/linux/tracehook.h~10_CLONE_ATTACH        2009-08-13 
17:51:52.000000000 +0200
+++ PU/include/linux/tracehook.h        2009-08-19 18:34:37.000000000 +0200
@@ -264,14 +264,6 @@ static inline void tracehook_report_clon
 {
        if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)))
                utrace_report_clone(clone_flags, child);
-       if (unlikely(task_ptrace(child))) {
-               /*
-                * It doesn't matter who attached/attaching to this
-                * task, the pending SIGSTOP is right in any case.
-                */
-               sigaddset(&child->pending.signal, SIGSTOP);
-               set_tsk_thread_flag(child, TIF_SIGPENDING);
-       }
 }
 
 /**
--- PU/kernel/ptrace.c~10_CLONE_ATTACH  2009-08-19 17:41:18.000000000 +0200
+++ PU/kernel/ptrace.c  2009-08-19 19:12:32.000000000 +0200
@@ -39,6 +39,8 @@ void __ptrace_link(struct task_struct *c
 }
 
 static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */
+static int ptrace_attach_task(struct task_struct *tracee);
+static void ptrace_abort_attach(struct task_struct *tracee);
 
 static void ptrace_detach_task(struct task_struct *child, int sig)
 {
@@ -211,6 +213,37 @@ static u32 ptrace_report_exit(enum utrac
        return utrace_ptrace_event(task, PTRACE_EVENT_EXIT, *code);
 }
 
+static void ptrace_clone_attach(struct task_struct *parent,
+                               struct task_struct *child)
+{
+       struct task_struct *tracer;
+       bool abort = true;
+
+       if (!parent->ptrace)
+               return;
+       if (unlikely(ptrace_attach_task(child))) {
+               WARN_ON(1);
+               return;
+       }
+
+       write_lock_irq(&tasklist_lock);
+       tracer = parent->parent;
+       if (!(tracer->flags & PF_EXITING) && parent->ptrace) {
+               child->ptrace = parent->ptrace;
+               __ptrace_link(child, tracer);
+               abort = false;
+       }
+       write_unlock_irq(&tasklist_lock);
+       if (unlikely(abort)) {
+               ptrace_abort_attach(child);
+               return;
+       }
+
+       sigaddset(&child->pending.signal, SIGSTOP);
+       set_tsk_thread_flag(child, TIF_SIGPENDING);
+       ptrace_update_utrace(child, NULL);
+}
+
 static u32 ptrace_report_clone(enum utrace_resume_action action,
                               struct utrace_engine *engine,
                               struct task_struct *parent,
@@ -218,7 +251,6 @@ static u32 ptrace_report_clone(enum utra
                               struct task_struct *child)
 {
        int event;
-       struct utrace_engine *child_engine;
 
        if ((clone_flags & CLONE_VFORK) &&
            (parent->ptrace & PT_TRACE_VFORK_DONE)) {
@@ -254,26 +286,8 @@ static u32 ptrace_report_clone(enum utra
         * Any of these reports implies auto-attaching the new child.
         * So does CLONE_PTRACE, even with no event to report.
         */
-       if (event || (clone_flags & CLONE_PTRACE)) {
-               child_engine = utrace_attach_task(child, UTRACE_ATTACH_CREATE |
-                                                 UTRACE_ATTACH_EXCLUSIVE |
-                                                 UTRACE_ATTACH_MATCH_OPS,
-                                                 &ptrace_utrace_ops,
-                                                 NULL);
-               if (unlikely(IS_ERR(child_engine))) {
-                       WARN_ON(1);     /* XXX */
-               } else {
-                       BUG_ON(!child->ptrace);
-                       /* XXX already set by old ptrace code
-                          task_lock(child);
-                          child->ptrace = parent->ptrace;
-                          child->parent = parent->parent;
-                          task_unlock(child);
-                       */
-                       ptrace_update_utrace(child, child_engine);
-                       utrace_engine_put(child_engine);
-               }
-       }
+       if (event || (clone_flags & CLONE_PTRACE))
+               ptrace_clone_attach(parent, child);
 
        if (event)
                return utrace_ptrace_event(parent, event, child->pid);

Reply via email to