Change ptrace_attach_task() to re-use the self-detaching engine first, then do utrace_attach_task(UTRACE_ATTACH_CREATE).
Unlike the previous version, ptrace_attach_task() just calls ptrace_lookup_engine() and changes context->resume. The only caller which can find the self-attaching engine is ptrace_atttach(), we can rely on ->cred_guard_mutex. Todo: re-check this all and cleanup the mess in ptrace_attach_task(). But first I'd like to know if you agree with this approach. --- kernel/ptrace.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) --- PU/kernel/ptrace.c~81_REUSE_DETACHING_ENGINE 2009-10-10 17:10:07.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-10 17:13:37.000000000 +0200 @@ -442,6 +442,22 @@ static int ptrace_attach_task(struct tas struct utrace_engine *engine; int err; + engine = ptrace_lookup_engine(tracee); + if (!IS_ERR(engine)) { + context = ptrace_context(engine); + if (context->resume == UTRACE_DETACH) { + /* we rely on ->cred_guard_mutex */ + context->resume = UTRACE_RESUME; + /* + * Make sure we don't race with ptrace_report_signal() + */ + utrace_barrier(tracee, engine); + if (engine->ops == &ptrace_utrace_ops) + goto finish; + } + utrace_engine_put(engine); + } + context = kzalloc(sizeof(*context), GFP_KERNEL); if (unlikely(!context)) return -ENOMEM; @@ -459,6 +475,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.