[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(¤t->sighand->siglock);
__set_current_state(TASK_RUNNING);
+ spin_unlock_irq(¤t->sighand->siglock);
+
if (clear_code)
current->exit_code = 0;
read_unlock(&tasklist_lock);
--
1.5.5.1
More information about the kernel
mailing list