Prev: [PATCH] NOMMU: Work around the lack of vmap()/vunmap() in firmware_loading_store() [ver #2]
Next: wd7000: typo spin_unlock_irq() => spin_lock_irq()
From: Eric Dumazet on 8 Apr 2010 10:00 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/ |