utrace_do_stop() sets utrace->stopped but leaves the tracee in TASK_STOPPED state. This means SIGCONT can wake up the tracee and fool the tracer.
Set ->state = TASK_TRACED and update the comments in utrace_do_stop() and utrace_finish_jctl(). Signed-off-by: Oleg Nesterov <o...@redhat.com> ---- kernel/utrace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) --- __UTRACE/kernel/utrace.c~3_STOP_TRACED 2009-07-31 02:15:34.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-31 02:25:32.000000000 +0200 @@ -788,8 +788,9 @@ static bool utrace_do_stop(struct task_s } else if (task_is_stopped(target)) { /* * Stopped is considered quiescent; when it wakes up, it will - * go through utrace_get_signal() before doing anything else. + * go through utrace_finish_jctl() before doing anything else. */ + __set_task_state(target, TASK_TRACED); utrace->stopped = stopped = true; } else if (!utrace->report && !utrace->interrupt) { utrace->report = 1; @@ -1646,9 +1647,8 @@ void utrace_finish_jctl(void) { struct utrace *utrace = task_utrace_struct(current); /* - * While in TASK_STOPPED, we can be considered safely - * stopped by utrace_do_stop(). Clear ->stopped if we - * were woken by signal. + * While in TASK_STOPPED, we can be considered safely stopped by + * utrace_do_stop(). Clear ->stopped if we were woken by SIGKILL. */ if (utrace->stopped) { spin_lock(&utrace->lock);