A killed tracee should do nothing until the tracer drops utrace->lock. Signed-off-by: Oleg Nesterov <o...@redhat.com> ---
include/linux/tracehook.h | 2 ++ include/linux/utrace.h | 2 ++ kernel/utrace.c | 16 +++++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) --- UTRACE/include/linux/tracehook.h~1_FINISH_STOP 2009-11-03 01:38:22.000000000 +0100 +++ UTRACE/include/linux/tracehook.h 2009-11-03 05:38:49.000000000 +0100 @@ -531,6 +531,8 @@ static inline int tracehook_notify_jctl( */ static inline void tracehook_finish_jctl(void) { + if (task_utrace_flags(current)) + utrace_finish_stop(); } #define DEATH_REAP -1 --- UTRACE/include/linux/utrace.h~1_FINISH_STOP 2009-11-03 01:38:22.000000000 +0100 +++ UTRACE/include/linux/utrace.h 2009-11-03 05:39:41.000000000 +0100 @@ -98,6 +98,8 @@ bool utrace_interrupt_pending(void) __attribute__((weak)); void utrace_resume(struct task_struct *, struct pt_regs *) __attribute__((weak)); +void utrace_finish_stop(void) + __attribute__((weak)); int utrace_get_signal(struct task_struct *, struct pt_regs *, siginfo_t *, struct k_sigaction *) __attribute__((weak)); --- UTRACE/kernel/utrace.c~1_FINISH_STOP 2009-11-03 01:38:22.000000000 +0100 +++ UTRACE/kernel/utrace.c 2009-11-03 06:10:10.000000000 +0100 @@ -701,7 +701,7 @@ static bool utrace_do_stop(struct task_s if (task_is_stopped(target)) { /* * Stopped is considered quiescent; when it wakes up, it will - * go through utrace_finish_jctl() before doing anything else. + * go through utrace_finish_stop() before doing anything else. */ spin_lock_irq(&target->sighand->siglock); if (likely(task_is_stopped(target))) @@ -809,6 +809,18 @@ static bool utrace_reset(struct task_str return !flags; } +void utrace_finish_stop(void) +{ + /* + * If we were task_is_traced() and then SIGKILL'ed, make + * sure we do nothing until the tracer drops utrace->lock. + */ + if (unlikely(__fatal_signal_pending(current))) { + struct utrace *utrace = task_utrace_struct(current); + spin_unlock_wait(&utrace->lock); + } +} + /* * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. * @task == current, @utrace == current->utrace, which is not locked. @@ -875,6 +887,8 @@ relock: schedule(); + utrace_finish_stop(); + /* * While in TASK_TRACED, we were considered "frozen enough". * Now that we woke up, it's crucial if we're supposed to be