Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

x86: be even more careful about checking the stack frame on dumping

lguest didn't initialize the kernel stack the way a real i386 kernel
does, and ended up triggering a corner-case in the stack frame checking
that doesn't happen on naive i386, and that the stack dumping didn't
handle quite right.

This makes the frame handling more correct, and tries to clarify the
code at the same time so that it's a bit more obvious what is going on.

Thanks to Rusty Russell for debugging the lguest failure-

Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+21 -12
+21 -12
arch/i386/kernel/traps.c
··· 100 100 int kstack_depth_to_print = 24; 101 101 static unsigned int code_bytes = 64; 102 102 103 - static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) 103 + static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned size) 104 104 { 105 105 return p > (void *)tinfo && 106 - p < (void *)tinfo + THREAD_SIZE - 3; 106 + p <= (void *)tinfo + THREAD_SIZE - size; 107 107 } 108 + 109 + /* The form of the top of the frame on the stack */ 110 + struct stack_frame { 111 + struct stack_frame *next_frame; 112 + unsigned long return_address; 113 + }; 108 114 109 115 static inline unsigned long print_context_stack(struct thread_info *tinfo, 110 116 unsigned long *stack, unsigned long ebp, 111 117 struct stacktrace_ops *ops, void *data) 112 118 { 113 - unsigned long addr; 114 - 115 119 #ifdef CONFIG_FRAME_POINTER 116 - while (valid_stack_ptr(tinfo, (void *)ebp)) { 117 - unsigned long new_ebp; 118 - addr = *(unsigned long *)(ebp + 4); 120 + struct stack_frame *frame = (struct stack_frame *)ebp; 121 + while (valid_stack_ptr(tinfo, frame, sizeof(*frame))) { 122 + struct stack_frame *next; 123 + unsigned long addr; 124 + 125 + addr = frame->return_address; 119 126 ops->address(data, addr); 120 127 /* 121 128 * break out of recursive entries (such as 122 129 * end_of_stack_stop_unwind_function). Also, 123 130 * we can never allow a frame pointer to 124 131 * move downwards! 125 - */ 126 - new_ebp = *(unsigned long *)ebp; 127 - if (new_ebp <= ebp) 132 + */ 133 + next = frame->next_frame; 134 + if (next <= frame) 128 135 break; 129 - ebp = new_ebp; 136 + frame = next; 130 137 } 131 138 #else 132 - while (valid_stack_ptr(tinfo, stack)) { 139 + while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) { 140 + unsigned long addr; 141 + 133 142 addr = *stack++; 134 143 if (__kernel_text_address(addr)) 135 144 ops->address(data, addr);