diff options
author | Andi Kleen <ak@suse.de> | 2006-11-28 14:12:59 -0500 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-11-28 14:12:59 -0500 |
commit | c547c77ee4d0408907847f64c403df1bf2f9c7a0 (patch) | |
tree | ffbc35f7dcbf7b1b57f220c1e1a555bed24a6089 /arch/x86_64 | |
parent | 38b5b036b91248be8033d42dd0778b1c75c5af58 (diff) |
[PATCH] x86-64: Use stricter in process stack check for unwinder
Previously it would check for alignment only, which could break
if the stack pointer was unaligned. Now explicitely check if the
stack pointer is in the stack page of the current process.
Ported from i386.
Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/kernel/traps.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index a153d0a01b72..0d65b22f229c 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c | |||
@@ -242,12 +242,19 @@ static int dump_trace_unwind(struct unwind_frame_info *info, void *context) | |||
242 | * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack | 242 | * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack |
243 | */ | 243 | */ |
244 | 244 | ||
245 | static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) | ||
246 | { | ||
247 | void *t = (void *)tinfo; | ||
248 | return p > t && p < t + THREAD_SIZE - 3; | ||
249 | } | ||
250 | |||
245 | void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack, | 251 | void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack, |
246 | struct stacktrace_ops *ops, void *data) | 252 | struct stacktrace_ops *ops, void *data) |
247 | { | 253 | { |
248 | const unsigned cpu = smp_processor_id(); | 254 | const unsigned cpu = smp_processor_id(); |
249 | unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; | 255 | unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; |
250 | unsigned used = 0; | 256 | unsigned used = 0; |
257 | struct thread_info *tinfo; | ||
251 | 258 | ||
252 | if (!tsk) | 259 | if (!tsk) |
253 | tsk = current; | 260 | tsk = current; |
@@ -370,7 +377,8 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s | |||
370 | /* | 377 | /* |
371 | * This handles the process stack: | 378 | * This handles the process stack: |
372 | */ | 379 | */ |
373 | HANDLE_STACK (((long) stack & (THREAD_SIZE-1)) != 0); | 380 | tinfo = current_thread_info(); |
381 | HANDLE_STACK (valid_stack_ptr(tinfo, stack)); | ||
374 | #undef HANDLE_STACK | 382 | #undef HANDLE_STACK |
375 | } | 383 | } |
376 | EXPORT_SYMBOL(dump_trace); | 384 | EXPORT_SYMBOL(dump_trace); |