[PATCH 03/19] ptrace: take ->siglock around s/TRACED/RUNNING/

Oleg Nesterov oleg at redhat.com
Fri Jul 1 00:21:04 UTC 2011


change ptrace_resume() and ptrace_stop() to take ->siglock around changing
task->state from TRACED to RUNNING.

With this patch __TASK_TRACED/STOPPED bits are fully protected by ->siglock,
nobody can set or clear these bits without ->siglock held.

Signed-off-by: Oleg Nesterov <oleg at redhat.com>
---
 kernel/ptrace.c |    8 +++++++-
 kernel/signal.c |    3 +++
 2 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 2df1157..9988b13 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -534,6 +534,8 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
 static int ptrace_resume(struct task_struct *child, long request,
 			 unsigned long data)
 {
+	unsigned long flags;
+
 	if (!valid_signal(data))
 		return -EIO;
 
@@ -562,7 +564,11 @@ static int ptrace_resume(struct task_struct *child, long request,
 	}
 
 	child->exit_code = data;
-	wake_up_state(child, __TASK_TRACED);
+
+	if (lock_task_sighand(child, &flags)) {
+		wake_up_state(child, __TASK_TRACED);
+		unlock_task_sighand(child, &flags);
+	}
 
 	return 0;
 }
diff --git a/kernel/signal.c b/kernel/signal.c
index ff76786..2138cee 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1799,7 +1799,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 		if (gstop_done)
 			do_notify_parent_cldstop(current, false, why);
 
+		spin_lock_irq(&current->sighand->siglock);
 		__set_current_state(TASK_RUNNING);
+		spin_unlock_irq(&current->sighand->siglock);
+
 		if (clear_code)
 			current->exit_code = 0;
 		read_unlock(&tasklist_lock);
-- 
1.5.5.1




More information about the kernel mailing list