Change ptrace_attach_task() to re-use the self-detaching engine first,
then do utrace_attach_task(UTRACE_ATTACH_CREATE).

Todo:

        - re-check this all (and test)

        - rename check()

        - cleanups the mess in ptrace_attach_task()

        - ptrace_detach_task() should clear options/flags, if we re-use
          this engine then ptrace_attach_task()->utrace_set_events()
          happens a bit late.

---

 kernel/ptrace.c |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

--- PU/kernel/ptrace.c~78_REUSE_PARTING_ENGINE  2009-10-09 18:51:56.000000000 
+0200
+++ PU/kernel/ptrace.c  2009-10-09 19:04:34.000000000 +0200
@@ -431,6 +431,15 @@ static inline int __ptrace_set_options(s
        return utrace_set_events(target, engine, events);
 }
 
+static bool check(void *data)
+{
+       struct ptrace_context *context = data;
+       if (context->resume != UTRACE_DETACH)
+               return false;
+       context->resume = UTRACE_RESUME;
+       return true;
+}
+
 /*
  * Attach a utrace engine for ptrace and set up its event mask.
  * Returns error code or 0 on success.
@@ -441,6 +450,20 @@ static int ptrace_attach_task(struct tas
        struct utrace_engine *engine;
        int err;
 
+       engine = utrace_attach_task(tracee, UTRACE_ATTACH_MATCH_OPS |
+                                               UTRACE_ATTACH_MATCH_CHECK,
+                                               &ptrace_utrace_ops, check);
+       if (!IS_ERR(engine)) {
+               /*
+                * Make sure we don't race with ptrace_report_signal()
+                */
+               utrace_barrier(tracee, engine);
+               if (engine->ops != &ptrace_utrace_ops)
+                       utrace_engine_put(engine);
+               else
+                       goto finish;
+       }
+
        context = kzalloc(sizeof(*context), GFP_KERNEL);
        if (unlikely(!context))
                return -ENOMEM;
@@ -458,6 +481,7 @@ static int ptrace_attach_task(struct tas
                kfree(context);
                return err;
        }
+finish:
        /*
         * It can fail only if the tracee is dead, the caller
         * must notice this before setting PT_PTRACED.

Reply via email to