ACK: [Oneiric CVE 1/3] ptrace: introduce signal_wake_up_state() and ptrace_signal_wake_up()

Colin Ian King colin.king at canonical.com
Tue Feb 19 16:04:16 UTC 2013


On 19/02/13 14:18, Luis Henriques wrote:
> From: Oleg Nesterov <oleg at redhat.com>
>
> CVE-2013-0871
>
> 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 at redhat.com>
> Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
> (backported from commit 910ffdb18a6408e14febbb6e4b6840fd2c928c82)
>
> Conflicts:
> 	kernel/ptrace.c
> 	kernel/signal.c
> Signed-off-by: Luis Henriques <luis.henriques at canonical.com>
> ---
>   include/linux/sched.h | 11 ++++++++++-
>   kernel/ptrace.c       |  4 ++--
>   kernel/signal.c       | 12 +++---------
>   3 files changed, 15 insertions(+), 12 deletions(-)
>
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 547e4a8..ed0f39a 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -2571,7 +2571,16 @@ static inline void thread_group_cputime_init(struct signal_struct *sig)
>   extern void recalc_sigpending_and_wake(struct task_struct *t);
>   extern void recalc_sigpending(void);
>
> -extern void signal_wake_up(struct task_struct *t, int resume_stopped);
> +extern void signal_wake_up_state(struct task_struct *t, unsigned int state);
> +
> +static inline void signal_wake_up(struct task_struct *t, bool resume)
> +{
> +	signal_wake_up_state(t, resume ? TASK_WAKEKILL : 0);
> +}
> +static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume)
> +{
> +	signal_wake_up_state(t, resume ? __TASK_TRACED : 0);
> +}
>
>   /*
>    * Wrappers for p->thread_info->cpu access. No-op on UP.
> diff --git a/kernel/ptrace.c b/kernel/ptrace.c
> index 2df1157..d77fa9e 100644
> --- a/kernel/ptrace.c
> +++ b/kernel/ptrace.c
> @@ -92,7 +92,7 @@ void __ptrace_unlink(struct task_struct *child)
>   	 * TASK_KILLABLE sleeps.
>   	 */
>   	if (child->group_stop & GROUP_STOP_PENDING || task_is_traced(child))
> -		signal_wake_up(child, task_is_traced(child));
> +		ptrace_signal_wake_up(child, true);
>
>   	spin_unlock(&child->sighand->siglock);
>   }
> @@ -245,7 +245,7 @@ static int ptrace_attach(struct task_struct *task)
>   	 */
>   	if (task_is_stopped(task)) {
>   		task->group_stop |= GROUP_STOP_PENDING | GROUP_STOP_TRAPPING;
> -		signal_wake_up(task, 1);
> +		signal_wake_up_state(task, __TASK_STOPPED);
>   		wait_trap = true;
>   	}
>
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 43fee1c..8b0dd5b 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)
>    * 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);
>   }
>
>

ptrace_attach() for Oneiric does not support PTRACE_INTERRUPT or 
PTRACE_LISTEN which this backport has to omit, so that is sane looking 
to me.

Acked-by: Colin Ian King <colin.king at canonical.com>




More information about the kernel-team mailing list