On 07/22, Roland McGrath wrote:
>
> > This means ptrace_check_attach() can succeed but the tracee can even return
> > to the user-space after that, no? There is no guarantee utrace_get_signal()
> > will call finish_resume_report(). For example, if there are no pending
> > signals, we just clear ->stopped and return after dequeue_signal().
>
> Yes, I think you're right.  I think the "if (unlikely(utrace->stopped)) {"
> case in utrace_get_signal() needs to do some variant of utrace_reset.  If
> any engine_wants_stop() then it should not dequeue a signal even if one is
> ready, and probably it should also not do any spontaneous report.

Hmm. If ->stopped == T after return from do_signal_stop()->schedule(),
then we must have the engine which is engine_wants_stop(), no?

> OTOH perhaps it should do a spontaneous report in that case, so that if you
> used utrace_control(,,UTRACE_STOP) while in TASK_STOPPED, you get a
> UTRACE_SIGNAL_REPORT callback at SIGCONT time.  If that's the plan, then
> all we need is utrace_do_stop()'s task_is_stopped() case to set ->report
> too (and set_notify_resume for the invariant, though it's superfluous really).

Damn. Just can't think today...

Roland, can we just remove all code which plays with ->stopped in
utrace_report_jctl() and utrace_get_signal(), and do something like


        --- kernel/utrace.c
        +++ kernel/utrace.c
        @@ -390,6 +390,13 @@ static bool utrace_stop(struct task_stru
                 * for stop signals and SIGCONT.
                 */
                spin_lock(&utrace->lock);
        +
        +       return utrace_stop_locked(task, utrace, report);
        +}
        +
        +bool utrace_stop_locked(struct task_struct *task, struct utrace 
*utrace,
        +                       bool report)
        +{
                spin_lock_irq(&task->sighand->siglock);
         
                if (unlikely(sigismember(&task->pending.signal, SIGKILL))) {
        --- kernel/signal.c
        +++ kernel/signal.c
        @@ -1602,6 +1602,16 @@ static int do_signal_stop(int signr)
                do {
                        schedule();
                } while (try_to_freeze());
        +
        +       // needs a tracehook helper
        +       if (utrace->stopped) {
        +               spin_lock(&utrace->lock);
        +               if (utrace->stopped)
        +                       utrace_stop_locked();
        +               else
        +                       spin_unlock(&utrace->lock);
        +       }
        +
                /*
                 * Now we don't run again until continued.
                 */

No?

Oleg.

Reply via email to