diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/dumpstack_32.c | 19 | ||||
-rw-r--r-- | arch/x86/kernel/dumpstack_64.c | 2 |
2 files changed, 14 insertions, 7 deletions
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index 4e67a005c7a1..466d55dfeb87 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c | |||
@@ -28,10 +28,16 @@ void printk_address(unsigned long address, int reliable) | |||
28 | } | 28 | } |
29 | 29 | ||
30 | static inline int valid_stack_ptr(struct thread_info *tinfo, | 30 | static inline int valid_stack_ptr(struct thread_info *tinfo, |
31 | void *p, unsigned int size) | 31 | void *p, unsigned int size, void *end) |
32 | { | 32 | { |
33 | void *t = tinfo; | 33 | void *t = tinfo; |
34 | return p > t && p <= t + THREAD_SIZE - size; | 34 | if (end) { |
35 | if (p < end && p >= (end-THREAD_SIZE)) | ||
36 | return 1; | ||
37 | else | ||
38 | return 0; | ||
39 | } | ||
40 | return p > t && p < t + THREAD_SIZE - size; | ||
35 | } | 41 | } |
36 | 42 | ||
37 | /* The form of the top of the frame on the stack */ | 43 | /* The form of the top of the frame on the stack */ |
@@ -43,16 +49,17 @@ struct stack_frame { | |||
43 | static inline unsigned long | 49 | static inline unsigned long |
44 | print_context_stack(struct thread_info *tinfo, | 50 | print_context_stack(struct thread_info *tinfo, |
45 | unsigned long *stack, unsigned long bp, | 51 | unsigned long *stack, unsigned long bp, |
46 | const struct stacktrace_ops *ops, void *data) | 52 | const struct stacktrace_ops *ops, void *data, |
53 | unsigned long *end) | ||
47 | { | 54 | { |
48 | struct stack_frame *frame = (struct stack_frame *)bp; | 55 | struct stack_frame *frame = (struct stack_frame *)bp; |
49 | 56 | ||
50 | while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) { | 57 | while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) { |
51 | unsigned long addr; | 58 | unsigned long addr; |
52 | 59 | ||
53 | addr = *stack; | 60 | addr = *stack; |
54 | if (__kernel_text_address(addr)) { | 61 | if (__kernel_text_address(addr)) { |
55 | if ((unsigned long) stack == bp + 4) { | 62 | if ((unsigned long) stack == bp + sizeof(long)) { |
56 | ops->address(data, addr, 1); | 63 | ops->address(data, addr, 1); |
57 | frame = frame->next_frame; | 64 | frame = frame->next_frame; |
58 | bp = (unsigned long) frame; | 65 | bp = (unsigned long) frame; |
@@ -96,7 +103,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, | |||
96 | 103 | ||
97 | context = (struct thread_info *) | 104 | context = (struct thread_info *) |
98 | ((unsigned long)stack & (~(THREAD_SIZE - 1))); | 105 | ((unsigned long)stack & (~(THREAD_SIZE - 1))); |
99 | bp = print_context_stack(context, stack, bp, ops, data); | 106 | bp = print_context_stack(context, stack, bp, ops, data, NULL); |
100 | /* | 107 | /* |
101 | * Should be after the line below, but somewhere | 108 | * Should be after the line below, but somewhere |
102 | * in early boot context comes out corrupted and we | 109 | * in early boot context comes out corrupted and we |
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 563554c90686..361afa8864b4 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c | |||
@@ -141,7 +141,7 @@ print_context_stack(struct thread_info *tinfo, | |||
141 | 141 | ||
142 | addr = *stack; | 142 | addr = *stack; |
143 | if (__kernel_text_address(addr)) { | 143 | if (__kernel_text_address(addr)) { |
144 | if ((unsigned long) stack == bp + 8) { | 144 | if ((unsigned long) stack == bp + sizeof(long)) { |
145 | ops->address(data, addr, 1); | 145 | ops->address(data, addr, 1); |
146 | frame = frame->next_frame; | 146 | frame = frame->next_frame; |
147 | bp = (unsigned long) frame; | 147 | bp = (unsigned long) frame; |