tracehook_report_exit() calls ptrace_utrace_exit() to early. We don't have PF_EXITING yet, we can race with ptrace_traceme().
Granted, exit_ptrace/ptrace_utrace_exit should be reworked later. Just a minimal fix for now. --- include/linux/ptrace.h | 2 -- include/linux/tracehook.h | 2 -- kernel/ptrace.c | 20 +++++++++++--------- 3 files changed, 11 insertions(+), 13 deletions(-) --- PU/include/linux/ptrace.h~04_PTRACE_EXIT 2009-08-13 15:19:18.000000000 +0200 +++ PU/include/linux/ptrace.h 2009-08-13 17:53:02.000000000 +0200 @@ -131,8 +131,6 @@ static inline int task_ptrace(struct tas return task->ptrace; } -extern void ptrace_utrace_exit(struct task_struct *); - /** * ptrace_init_task - initialize ptrace state for a new child * @child: new child task --- PU/include/linux/tracehook.h~04_PTRACE_EXIT 2009-08-13 15:50:27.000000000 +0200 +++ PU/include/linux/tracehook.h 2009-08-13 17:51:52.000000000 +0200 @@ -195,8 +195,6 @@ static inline void tracehook_report_exit { if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT))) utrace_report_exit(exit_code); - if (unlikely(!list_empty(¤t->ptraced))) - ptrace_utrace_exit(current); } /** --- PU/kernel/ptrace.c~04_PTRACE_EXIT 2009-08-13 17:35:29.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-13 17:55:13.000000000 +0200 @@ -70,15 +70,6 @@ static void ptrace_detach_task(struct ta utrace_engine_put(engine); } -void ptrace_utrace_exit(struct task_struct *task) -{ - struct task_struct *child; - read_lock(&tasklist_lock); - list_for_each_entry(child, &task->ptraced, ptrace_entry) - ptrace_detach_task(child, 0); - read_unlock(&tasklist_lock); -} - /* * unptrace a task: move it back to its original parent and * remove it from the ptrace list. @@ -810,6 +801,15 @@ int ptrace_detach(struct task_struct *ch return 0; } +static void ptrace_utrace_exit(struct task_struct *task) +{ + struct task_struct *child; + read_lock(&tasklist_lock); + list_for_each_entry(child, &task->ptraced, ptrace_entry) + ptrace_detach_task(child, 0); + read_unlock(&tasklist_lock); +} + /* * Detach all tasks we were using ptrace on. */ @@ -818,6 +818,8 @@ void exit_ptrace(struct task_struct *tra struct task_struct *p, *n; LIST_HEAD(ptrace_dead); + ptrace_utrace_exit(tracer); + write_lock_irq(&tasklist_lock); list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) { if (__ptrace_detach(tracer, p))