Re: ptrace.2: PTRACE_KILL needs a stopped process too

From: Pedro Alves
Date: Wed May 02 2012 - 08:06:36 EST


On 04/22/2012 09:04 PM, Oleg Nesterov wrote:

> On 04/23, Michael Kerrisk (man-pages) wrote:
>>
>> [widening CC]
>
> add more CC's
>
>> The man page says "For requests other than PTRACE_KILL,
>
> Argh, PTRACE_KILL again.
>
> You know, I simply do not know what it was supposed to do. I can only
> see what the code actually does.
>
>> the child process
>> must be stopped."
>
> Yes and no.
>
> Yes, ptrace(PTRACE_KILL) "succeeds" even if the tracee is not stopped.
>
> No, it has no effect if the tracee is not stopped.
>
> All I can say is: PTRACE_KILL should never exist. If you want to kill
> the tracee, you can do kill(SIGKILL).
>
> Roughly, ptrace(PTRACE_KILL) is equal to ptrace(PTRACE_CONT, SIGKILL)
> except it always returns 0.
>
>> If the man page is describing actual intended kernel behavior, then it's a
>> fairly long-standing kernel bug.
>
> Perhaps. May be it should simply do kill(SIGKILL), but then it is not
> clear why do we have PTRACE_KILL. And once again, I was never able to
> understand the supposed behaviour.
>
> Personally, I think we should fix the documentation. And imho the only
> possible fix is to add this note: do not ever use PTRACE_KILL.


Yeah. Here's what gdb's gdbserver does nowadays (gdb does the exact same,
though only gdbserver's version has this comment):

static void
linux_kill_one_lwp (struct lwp_info *lwp)
{
int pid = lwpid_of (lwp);

/* PTRACE_KILL is unreliable. After stepping into a signal handler,
there is no signal context, and ptrace(PTRACE_KILL) (or
ptrace(PTRACE_CONT, SIGKILL), pretty much the same) acts like
ptrace(CONT, pid, 0,0) and just resumes the tracee. A better
alternative is to kill with SIGKILL. We only need one SIGKILL
per process, not one for each thread. But since we still support
linuxthreads, and we also support debugging programs using raw
clone without CLONE_THREAD, we send one for each thread. For
years, we used PTRACE_KILL only, so we're being a bit paranoid
about some old kernels where PTRACE_KILL might work better
(dubious if there are any such, but that's why it's paranoia), so
we try SIGKILL first, PTRACE_KILL second, and so we're fine
everywhere. */

errno = 0;
kill (pid, SIGKILL);
if (debug_threads)
fprintf (stderr,
"LKL: kill (SIGKILL) %s, 0, 0 (%s)\n",
target_pid_to_str (ptid_of (lwp)),
errno ? strerror (errno) : "OK");

errno = 0;
ptrace (PTRACE_KILL, pid, 0, 0);
if (debug_threads)
fprintf (stderr,
"LKL: PTRACE_KILL %s, 0, 0 (%s)\n",
target_pid_to_str (ptid_of (lwp)),
errno ? strerror (errno) : "OK");
}

--
Pedro Alves
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/