From: Jerome Marchand <jmarchan@redhat.com> Date: Mon, 20 Oct 2008 16:08:34 +0200 Subject: [misc] ptrace: fix exec report Message-id: 48FC90E2.60004@redhat.com O-Subject: [RHEL5 Patch] ptrace: fix exec report Bugzilla: 455060 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=455060 Description: A traced process executing execve() is stopped by a SIGTRAP. If the tracer uses ptrace(PTRACE_KILL...) to kill it, the tracee continues his execution instead of beeing killed. The tracee is not stopped by a real SIGTRAP signal but just put SIGTRAP in current->exit_code and notifies the tracer. The problem is that ptrace signal injection does not work outside the context of a real signal and the tracee never get the SIGKILL signal. Solution: Send a real SIGTRAP to stop the tracee if PTRACE_O_TRACEEXEC option is not set. That means that a process stopped in execve() when PTRACE_O_TRACEEXEC is set, is still not killable by PTRACE_KILL. If PTRACE_O_TRACEEXEC is not set, we can send any kind of signal to the tracee (including of course SIGKILL). That behaviour matchs upstream. Brew build: https://brewweb.devel.redhat.com/taskinfo?taskID=1517658 Test status: Build and test on i686. Regards, Jerome diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 2c363b8..256ac34 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -1943,9 +1943,16 @@ ptrace_report_exec(struct utrace_attached_engine *engine, if (unlikely(state == NULL)) return UTRACE_ACTION_RESUME; - return ptrace_event(engine, tsk, state, - (state->options & PTRACE_O_TRACEEXEC) - ? PTRACE_EVENT_EXEC : 0); + if (state->options & PTRACE_O_TRACEEXEC) + return ptrace_event(engine, tsk, state, PTRACE_EVENT_EXEC); + + /* + * Without PTRACE_O_TRACEEXEC, this is not a stop in the + * ptrace_notify() style. Instead, it's a regular signal. + * The difference is in where the real stop takes place and + * what ptrace can do with tsk->exit_code there. + */ + send_sig(SIGTRAP, tsk, 0); } static u32