[PATCH 1/1] re-introduce utrace_finish_stop() to fix the race with SIGKILL

Oleg Nesterov oleg at redhat.com
Tue Nov 3 05:38:43 UTC 2009


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

Signed-off-by: Oleg Nesterov <oleg at 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




More information about the utrace-devel mailing list