A tracee must not return to user mode with ->signal_handler = 1.
And, ->signal_handler = 1 must not survive when all detaches are
detached.

But, suppose (for simplicity) we have a single engine attached, and
utrace_signal_handler() sets ->signal_handler = 1.

Suppose signal_pending() = T. The tracee calls get_signal_to_deliver()
again.

It is possible that the tracee will call tracehook_notify_jctl() before
tracehook_get_signal(). Because another thread can start the group stop,
or because SIGNAL_STOP_CONTINUED is set.

The tracer does UTRACE_DETACH or ->report_jctl() returns UTRACE_DETACH.

REPORT()->finish_report() notices report->detaches and calls utrace_reset().

utrace_reset() completes UTRACE_DETACH, and clears ->utrace_flags.

The tracee return to user mode bypassing utrace_get_signal() and
utrace_resume() because task_utrace_flags() == 0.

So far this is OK, the task is not traced. But, when the new tracer
attaches, utrace->signal_handler is still true, the next report_signal
will use UTRACE_SIGNAL_HANDLER.

Signed-off-by: Oleg Nesterov <o...@redhat.com>

--- __UTRACE/kernel/utrace.c~2_SIGNAL_HANDLER_LEAK      2009-08-26 
12:30:38.000000000 +0200
+++ __UTRACE/kernel/utrace.c    2009-08-26 13:51:10.000000000 +0200
@@ -768,23 +768,20 @@ static void utrace_reset(struct task_str
        }
 
        task->utrace_flags = flags;
-
-       if (wake)
-               utrace_wakeup(task, utrace);
-
-       /*
-        * If any engines are left, we're done.
-        */
-       spin_unlock(&utrace->lock);
        if (!flags) {
                /*
                 * No more engines, cleared out the utrace.
                 */
+               utrace->interrupt = utrace->report = utrace->signal_handler = 0;
 
                if (action)
                        *action = UTRACE_RESUME;
        }
 
+       if (wake)
+               utrace_wakeup(task, utrace);
+       spin_unlock(&utrace->lock);
+
        put_detached_list(&detached);
 }
 

Reply via email to