A killed tracee should do nothing until the tracer drops utrace->lock.

Signed-off-by: Oleg Nesterov <o...@redhat.com>
---

 include/linux/tracehook.h |    2 ++
 include/linux/utrace.h    |    2 ++
 kernel/utrace.c           |   16 +++++++++++++++-
 3 files changed, 19 insertions(+), 1 deletion(-)

--- UTRACE/include/linux/tracehook.h~1_FINISH_STOP      2009-11-03 
01:38:22.000000000 +0100
+++ UTRACE/include/linux/tracehook.h    2009-11-03 05:38:49.000000000 +0100
@@ -531,6 +531,8 @@ static inline int tracehook_notify_jctl(
  */
 static inline void tracehook_finish_jctl(void)
 {
+       if (task_utrace_flags(current))
+               utrace_finish_stop();
 }
 
 #define DEATH_REAP                     -1
--- UTRACE/include/linux/utrace.h~1_FINISH_STOP 2009-11-03 01:38:22.000000000 
+0100
+++ UTRACE/include/linux/utrace.h       2009-11-03 05:39:41.000000000 +0100
@@ -98,6 +98,8 @@ bool utrace_interrupt_pending(void)
        __attribute__((weak));
 void utrace_resume(struct task_struct *, struct pt_regs *)
        __attribute__((weak));
+void utrace_finish_stop(void)
+       __attribute__((weak));
 int utrace_get_signal(struct task_struct *, struct pt_regs *,
                      siginfo_t *, struct k_sigaction *)
        __attribute__((weak));
--- UTRACE/kernel/utrace.c~1_FINISH_STOP        2009-11-03 01:38:22.000000000 
+0100
+++ UTRACE/kernel/utrace.c      2009-11-03 06:10:10.000000000 +0100
@@ -701,7 +701,7 @@ static bool utrace_do_stop(struct task_s
        if (task_is_stopped(target)) {
                /*
                 * Stopped is considered quiescent; when it wakes up, it will
-                * go through utrace_finish_jctl() before doing anything else.
+                * go through utrace_finish_stop() before doing anything else.
                 */
                spin_lock_irq(&target->sighand->siglock);
                if (likely(task_is_stopped(target)))
@@ -809,6 +809,18 @@ static bool utrace_reset(struct task_str
        return !flags;
 }
 
+void utrace_finish_stop(void)
+{
+       /*
+        * If we were task_is_traced() and then SIGKILL'ed, make
+        * sure we do nothing until the tracer drops utrace->lock.
+        */
+       if (unlikely(__fatal_signal_pending(current))) {
+               struct utrace *utrace = task_utrace_struct(current);
+               spin_unlock_wait(&utrace->lock);
+       }
+}
+
 /*
  * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up.
  * @task == current, @utrace == current->utrace, which is not locked.
@@ -875,6 +887,8 @@ relock:
 
        schedule();
 
+       utrace_finish_stop();
+
        /*
         * While in TASK_TRACED, we were considered "frozen enough".
         * Now that we woke up, it's crucial if we're supposed to be

Reply via email to