[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