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.