Add the new helper, ptrace_signal_wake_up(), change ptrace.c to use
it instead of signal_wake_up().

The new helper does almost the same, except:

        - it doesn't use the TASK_WAKEKILL bit to wake up the TRACED
          or STOPPED task, it uses __TASK_STOPPED | __TASK_TRACED
          explicitly. This is what ptrace actually wants, it should
          never wake up a TASK_KILLABLE task.

          This should be cleanuped upatream, signal_wake_up() should
          take the state as an argument, not a boolean. Until then
          we add a new static helper.

        - it uses wake_up_quiescent() instead of wake_up_state().

Thereafter every change from STOPPED/TRACED to RUNNING is done via
wake_up_quiescent().

Signed-off-by: Oleg Nesterov <o...@redhat.com>
---
 kernel/ptrace.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 26ae214..0b2aba5 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -24,6 +24,18 @@
 #include <linux/regset.h>
 #include <linux/hw_breakpoint.h>
 
+static void ptrace_signal_wake_up(struct task_struct *p, int quiescent)
+{
+       unsigned int state;
+
+       set_tsk_thread_flag(p, TIF_SIGPENDING);
+
+       state = TASK_INTERRUPTIBLE;
+       if (quiescent)
+               state |= (__TASK_STOPPED | __TASK_TRACED);
+       if (!wake_up_quiescent(p, state))
+               kick_process(p);
+}
 
 /*
  * ptrace a task: make the debugger its new parent and
@@ -92,7 +104,7 @@ void __ptrace_unlink(struct task_struct *child)
         * TASK_KILLABLE sleeps.
         */
        if (child->group_stop & GROUP_STOP_PENDING || task_is_traced(child))
-               signal_wake_up(child, task_is_traced(child));
+               ptrace_signal_wake_up(child, task_is_traced(child));
 
        spin_unlock(&child->sighand->siglock);
 }
@@ -245,7 +257,7 @@ static int ptrace_attach(struct task_struct *task)
         */
        if (task_is_stopped(task)) {
                task->group_stop |= GROUP_STOP_PENDING | GROUP_STOP_TRAPPING;
-               signal_wake_up(task, 1);
+               ptrace_signal_wake_up(task, 1);
                wait_trap = true;
        }
 
-- 
1.5.5.1


Reply via email to