> But ptrace_check_attach() needs the tracee to be already stopped.
> A bit ugly to ask the tracee to stop via UTRACE_STOP and then resume
> it if it was not already stopped. And I don't even understand how to
> do this correctly. (but again, I'll try to think later).

Ugly, but correct and simple.  It's only ugly when called in an error case.

> Apart from utrace_prepare_examine()->wait_task_inactive() and security
> checks, ptrace_check_attach() should do something like
> 
>       if (!task_stop_or_traced())
>               FAIL;
> 
>       if (SIGNAL_STOP_STOPPED ||      // JCTL stop
>           get_stop_event()) {         // it was stopped by us
> 
>           ... OK. s/STOPPED/TRACED/ and proceed ..
>       }
> 
>       FAIL;

Right.  That is fine as long as there are no races that can confuse it.
I don't see any off hand.

> Not sure. Suppose the tracer does PTRACE_SYSCALL and the tracee spins in
> user-mode. Another engine stops the tracee. In this case any ptrace()
> request should fail despite the fact the tracee is STOPPED or TRACED.

Correct (if it's in TASK_TRACED, not TASK_STOPPED).  It needs to test the
ptrace-stoppedness state in ptrace_context.  You only need any
UTRACE_STOP-related logic to counter any possible races with wakeup.  
i.e., if the stoppedness state is still left when you resume and cleared by
the tracee's own callbacks, you would get a false positive in case the
tracee had not been scheduled yet.  Since the ptrace-stoppedness should
never be indicated without the engine being in UTRACE_STOP state, the only
other race is with SIGKILL wakeups.  That one probably doesn't matter,
since it's no different from the SIGKILL wakeup coming just after
ptrace_check_attach() returns 0.


Thanks,
Roland

Reply via email to