diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-02-19 17:31:08 +0000 |
---|---|---|
committer | Willy Tarreau <w@1wt.eu> | 2013-06-10 11:42:19 +0200 |
commit | 905f1272f58fbeceee4f5b66527a0b1c367f8c57 (patch) | |
tree | 1fb20d56732e70f027c5335ddeb720697d21ac82 /kernel | |
parent | fd2ab7dcdaaf7fd5ec4e1e702b405610069f052c (diff) |
ptrace: introduce signal_wake_up_state() and ptrace_signal_wake_up()
ptrace: introduce signal_wake_up_state() and ptrace_signal_wake_up()
CVE-2013-0871
BugLink: http://bugs.launchpad.net/bugs/1129192
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>
(backported from commit 910ffdb18a6408e14febbb6e4b6840fd2c928c82)
Conflicts:
kernel/ptrace.c
kernel/signal.c
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
Acked-by: Colin King <colin.king@canonical.com>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/ptrace.c | 2 | ||||
-rw-r--r-- | kernel/signal.c | 12 |
2 files changed, 4 insertions, 10 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index d8184b54023..37850f9db63 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -56,7 +56,7 @@ static void ptrace_untrace(struct task_struct *child) child->signal->group_stop_count) __set_task_state(child, TASK_STOPPED); else - signal_wake_up(child, 1); + ptrace_signal_wake_up(child, true); } spin_unlock(&child->sighand->siglock); } diff --git a/kernel/signal.c b/kernel/signal.c index df993fdf43f..b40f4f06421 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -516,23 +516,17 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) * No need to set need_resched since signal event passing * goes through ->blocked */ -void signal_wake_up(struct task_struct *t, int resume) +void signal_wake_up_state(struct task_struct *t, unsigned int state) { - unsigned int mask; - set_tsk_thread_flag(t, TIF_SIGPENDING); - /* - * For SIGKILL, we want to wake it up in the stopped/traced/killable + * TASK_WAKEKILL also means wake it up in the stopped/traced/killable * case. We don't check t->state here because there is a race with it * executing another processor and just now entering stopped state. * By using wake_up_state, we ensure the process will wake up and * handle its death signal. */ - mask = TASK_INTERRUPTIBLE; - if (resume) - mask |= TASK_WAKEKILL; - if (!wake_up_state(t, mask)) + if (!wake_up_state(t, state | TASK_INTERRUPTIBLE)) kick_process(t); } |