From: Eric Dumazet on
Le jeudi 08 avril 2010 à 14:32 +0200, Frederic Weisbecker a écrit :


>
> Can you please test this fix?
>
> Thanks.
>
> ---
> From 60d5c4e8498efc4a01abceef54ad3bc91993bf41 Mon Sep 17 00:00:00 2001
> From: Frederic Weisbecker <fweisbec(a)gmail.com>
> Date: Thu, 8 Apr 2010 14:05:50 +0200
> Subject: [PATCH] perf: Fix unsafe frame rewinding with hot regs fetching
>
> When we fetch the hot regs and rewind to the nth caller, it
> might happen that we dereference a frame pointer outside the
> kernel stack boundaries, like in this example:
>
> perf_trace_sched_switch+0xd5/0x120
> schedule+0x6b5/0x860
> retint_careful+0xd/0x21
>
> Since we directly dereference a userspace frame pointer here while
> rewinding behind retint_careful, this may end up in a crash.
>
> Fix this by simply using probe_kernel_address() when we rewind the
> frame pointer.
>
> This issue will have a much more proper fix in the next version of the
> perf_arch_fetch_caller_regs() API that will only need to rewind to the
> first caller.
>
> Reported-by: Eric Dumazet <eric.dumazet(a)gmail.com>
> Signed-off-by: Frederic Weisbecker <fweisbec(a)gmail.com>
> Cc: Peter Zijlstra <a.p.zijlstra(a)chello.nl>
> Cc: Arnaldo Carvalho de Melo <acme(a)redhat.com>
> Cc: Paul Mackerras <paulus(a)samba.org>
> Cc: David Miller <davem(a)davemloft.net>
> Cc: Archs <linux-arch(a)vger.kernel.org>
> ---
> arch/x86/kernel/dumpstack.h | 8 ++++++--
> 1 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kernel/dumpstack.h b/arch/x86/kernel/dumpstack.h
> index e39e771..e1a93be 100644
> --- a/arch/x86/kernel/dumpstack.h
> +++ b/arch/x86/kernel/dumpstack.h
> @@ -14,6 +14,8 @@
> #define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
> #endif
>
> +#include <linux/uaccess.h>
> +
> extern void
> show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
> unsigned long *stack, unsigned long bp, char *log_lvl);
> @@ -42,8 +44,10 @@ static inline unsigned long rewind_frame_pointer(int n)
> get_bp(frame);
>
> #ifdef CONFIG_FRAME_POINTER
> - while (n--)
> - frame = frame->next_frame;
> + while (n--) {
> + if (probe_kernel_address(&frame->next_frame, frame))
> + break;
> + }
> #endif
>
> return (unsigned long)frame;

Thanks, no more crash :)

Tested-by: Eric Dumazet <eric.dumazet(a)gmail.com>


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/