aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov2013-02-19 07:56:51 -0600
committerGreg Kroah-Hartman2013-03-03 16:09:05 -0600
commit964b12560e1d50f31bc1cc0ac662d52bdbdb6f40 (patch)
treebbc317c3b1173bd9ec8ece352ad4ddd3d9933924
parent603b86549a4d6928d1059b19df2dfc5d61070533 (diff)
downloadkernel-common-964b12560e1d50f31bc1cc0ac662d52bdbdb6f40.tar.gz
kernel-common-964b12560e1d50f31bc1cc0ac662d52bdbdb6f40.tar.xz
kernel-common-964b12560e1d50f31bc1cc0ac662d52bdbdb6f40.zip
ptrace: introduce signal_wake_up_state() and ptrace_signal_wake_up()
Upstream commit 910ffdb18a6408e14febbb6e4b6840fd2c928c82. Cleanup and preparation for the next change. signal_wake_up(resume => true) is overused. None of ptrace/jctl callers actually want to wakeup a TASK_WAKEKILL task, but they can't specify the necessary mask. Turn signal_wake_up() into signal_wake_up_state(state), reintroduce signal_wake_up() as a trivial helper, and add ptrace_signal_wake_up() which adds __TASK_TRACED. This way ptrace_signal_wake_up() can work "inside" ptrace_request() even if the tracee doesn't have the TASK_WAKEKILL bit set. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Michal Hocko <mhocko@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--include/linux/sched.h11
-rw-r--r--kernel/ptrace.c4
-rw-r--r--kernel/signal.c12
3 files changed, 15 insertions, 12 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 0dae42e7029..d728baba741 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2564,7 +2564,16 @@ static inline void thread_group_cputime_init(struct signal_struct *sig)
2564extern void recalc_sigpending_and_wake(struct task_struct *t); 2564extern void recalc_sigpending_and_wake(struct task_struct *t);
2565extern void recalc_sigpending(void); 2565extern void recalc_sigpending(void);
2566 2566
2567extern void signal_wake_up(struct task_struct *t, int resume_stopped); 2567extern void signal_wake_up_state(struct task_struct *t, unsigned int state);
2568
2569static inline void signal_wake_up(struct task_struct *t, bool resume)
2570{
2571 signal_wake_up_state(t, resume ? TASK_WAKEKILL : 0);
2572}
2573static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume)
2574{
2575 signal_wake_up_state(t, resume ? __TASK_TRACED : 0);
2576}
2568 2577
2569/* 2578/*
2570 * Wrappers for p->thread_info->cpu access. No-op on UP. 2579 * Wrappers for p->thread_info->cpu access. No-op on UP.
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 2df115790cd..d77fa9eb082 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -92,7 +92,7 @@ void __ptrace_unlink(struct task_struct *child)
92 * TASK_KILLABLE sleeps. 92 * TASK_KILLABLE sleeps.
93 */ 93 */
94 if (child->group_stop & GROUP_STOP_PENDING || task_is_traced(child)) 94 if (child->group_stop & GROUP_STOP_PENDING || task_is_traced(child))
95 signal_wake_up(child, task_is_traced(child)); 95 ptrace_signal_wake_up(child, true);
96 96
97 spin_unlock(&child->sighand->siglock); 97 spin_unlock(&child->sighand->siglock);
98} 98}
@@ -245,7 +245,7 @@ static int ptrace_attach(struct task_struct *task)
245 */ 245 */
246 if (task_is_stopped(task)) { 246 if (task_is_stopped(task)) {
247 task->group_stop |= GROUP_STOP_PENDING | GROUP_STOP_TRAPPING; 247 task->group_stop |= GROUP_STOP_PENDING | GROUP_STOP_TRAPPING;
248 signal_wake_up(task, 1); 248 signal_wake_up_state(task, __TASK_STOPPED);
249 wait_trap = true; 249 wait_trap = true;
250 } 250 }
251 251
diff --git a/kernel/signal.c b/kernel/signal.c
index 43fee1cf50d..8b0dd5bb4da 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -631,23 +631,17 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
631 * No need to set need_resched since signal event passing 631 * No need to set need_resched since signal event passing
632 * goes through ->blocked 632 * goes through ->blocked
633 */ 633 */
634void signal_wake_up(struct task_struct *t, int resume) 634void signal_wake_up_state(struct task_struct *t, unsigned int state)
635{ 635{
636 unsigned int mask;
637
638 set_tsk_thread_flag(t, TIF_SIGPENDING); 636 set_tsk_thread_flag(t, TIF_SIGPENDING);
639
640 /* 637 /*
641 * For SIGKILL, we want to wake it up in the stopped/traced/killable 638 * TASK_WAKEKILL also means wake it up in the stopped/traced/killable
642 * case. We don't check t->state here because there is a race with it 639 * case. We don't check t->state here because there is a race with it
643 * executing another processor and just now entering stopped state. 640 * executing another processor and just now entering stopped state.
644 * By using wake_up_state, we ensure the process will wake up and 641 * By using wake_up_state, we ensure the process will wake up and
645 * handle its death signal. 642 * handle its death signal.
646 */ 643 */
647 mask = TASK_INTERRUPTIBLE; 644 if (!wake_up_state(t, state | TASK_INTERRUPTIBLE))
648 if (resume)
649 mask |= TASK_WAKEKILL;
650 if (!wake_up_state(t, mask))
651 kick_process(t); 645 kick_process(t);
652} 646}
653 647