Skip to content

Commit

Permalink
[PATCH] x86: Make backtracer fallback logic more bullet-proof
Browse files Browse the repository at this point in the history
The unwinder fallback logic still had potential for falling through to
the legacy stack trace code without printing an indication (at once
serving as a separator) of this.

Further, the stack pointer retrieval for the fallback should be as
restrictive as possible (in order to avoid having the legacy stack
tracer try to access invalid memory). The patch tightens that, but
this could certainly be further improved.

Also making the call_trace command line option now conditional upon
CONFIG_STACK_UNWIND (as it's meaningless otherwise).

Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Jan Beulich authored and Linus Torvalds committed Aug 30, 2006
1 parent 61171b8 commit ea42405
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 22 deletions.
27 changes: 16 additions & 11 deletions arch/i386/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ asmlinkage void spurious_interrupt_bug(void);
asmlinkage void machine_check(void);

static int kstack_depth_to_print = 24;
#ifdef CONFIG_STACK_UNWIND
static int call_trace = 1;
#else
#define call_trace (-1)
#endif
ATOMIC_NOTIFIER_HEAD(i386die_chain);

int register_die_notifier(struct notifier_block *nb)
Expand Down Expand Up @@ -187,22 +191,21 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
if (unwind_init_blocked(&info, task) == 0)
unw_ret = show_trace_unwind(&info, log_lvl);
}
if (unw_ret > 0 && !arch_unw_user_mode(&info)) {
#ifdef CONFIG_STACK_UNWIND
print_symbol("DWARF2 unwinder stuck at %s\n",
UNW_PC(&info));
if (call_trace == 1) {
printk("Leftover inexact backtrace:\n");
if (UNW_SP(&info))
if (unw_ret > 0) {
if (call_trace == 1 && !arch_unw_user_mode(&info)) {
print_symbol("DWARF2 unwinder stuck at %s\n",
UNW_PC(&info));
if (UNW_SP(&info) >= PAGE_OFFSET) {
printk("Leftover inexact backtrace:\n");
stack = (void *)UNW_SP(&info);
} else if (call_trace > 1)
} else
printk("Full inexact backtrace again:\n");
} else if (call_trace >= 1)
return;
else
printk("Full inexact backtrace again:\n");
#else
} else
printk("Inexact backtrace:\n");
#endif
}
}

if (task == current) {
Expand Down Expand Up @@ -1241,6 +1244,7 @@ static int __init kstack_setup(char *s)
}
__setup("kstack=", kstack_setup);

#ifdef CONFIG_STACK_UNWIND
static int __init call_trace_setup(char *s)
{
if (strcmp(s, "old") == 0)
Expand All @@ -1254,3 +1258,4 @@ static int __init call_trace_setup(char *s)
return 1;
}
__setup("call_trace=", call_trace_setup);
#endif
28 changes: 17 additions & 11 deletions arch/x86_64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,11 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
}

static int kstack_depth_to_print = 12;
#ifdef CONFIG_STACK_UNWIND
static int call_trace = 1;
#else
#define call_trace (-1)
#endif

#ifdef CONFIG_KALLSYMS
# include <linux/kallsyms.h>
Expand Down Expand Up @@ -274,21 +278,21 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
if (unwind_init_blocked(&info, tsk) == 0)
unw_ret = show_trace_unwind(&info, NULL);
}
if (unw_ret > 0 && !arch_unw_user_mode(&info)) {
#ifdef CONFIG_STACK_UNWIND
unsigned long rip = info.regs.rip;
print_symbol("DWARF2 unwinder stuck at %s\n", rip);
if (call_trace == 1) {
printk("Leftover inexact backtrace:\n");
stack = (unsigned long *)info.regs.rsp;
} else if (call_trace > 1)
if (unw_ret > 0) {
if (call_trace == 1 && !arch_unw_user_mode(&info)) {
print_symbol("DWARF2 unwinder stuck at %s\n",
UNW_PC(&info));
if ((long)UNW_SP(&info) < 0) {
printk("Leftover inexact backtrace:\n");
stack = (unsigned long *)UNW_SP(&info);
} else
printk("Full inexact backtrace again:\n");
} else if (call_trace >= 1)
return;
else
printk("Full inexact backtrace again:\n");
#else
} else
printk("Inexact backtrace:\n");
#endif
}
}

/*
Expand Down Expand Up @@ -1120,6 +1124,7 @@ static int __init kstack_setup(char *s)
}
__setup("kstack=", kstack_setup);

#ifdef CONFIG_STACK_UNWIND
static int __init call_trace_setup(char *s)
{
if (strcmp(s, "old") == 0)
Expand All @@ -1133,3 +1138,4 @@ static int __init call_trace_setup(char *s)
return 1;
}
__setup("call_trace=", call_trace_setup);
#endif
1 change: 1 addition & 0 deletions include/asm-i386/unwind.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
#else

#define UNW_PC(frame) ((void)(frame), 0)
#define UNW_SP(frame) ((void)(frame), 0)

static inline int arch_unw_user_mode(const void *info)
{
Expand Down
1 change: 1 addition & 0 deletions include/asm-x86_64/unwind.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
#else

#define UNW_PC(frame) ((void)(frame), 0)
#define UNW_SP(frame) ((void)(frame), 0)

static inline int arch_unw_user_mode(const void *info)
{
Expand Down

0 comments on commit ea42405

Please sign in to comment.