x86: be more careful when walking back the frame pointer chain
When showing the stack backtrace, make sure that we never accept not only an unchanging frame pointer, but also a frame pointer that moves back down the stack frame. It must always grow up (toward older stack frames). I doubt this has triggered, but a subtly corrupt stack with extremely unlucky contents could cause us to loop forever on a bogus endless frame pointer chain. This review was triggered by much worse problems happening in some of the other stack unwinding code. Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
1ff5683043
commit
808dbbb6bb
1 changed files with 7 additions and 3 deletions
|
@ -129,15 +129,19 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
|
|||
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
while (valid_stack_ptr(tinfo, (void *)ebp)) {
|
||||
unsigned long new_ebp;
|
||||
addr = *(unsigned long *)(ebp + 4);
|
||||
ops->address(data, addr);
|
||||
/*
|
||||
* break out of recursive entries (such as
|
||||
* end_of_stack_stop_unwind_function):
|
||||
* end_of_stack_stop_unwind_function). Also,
|
||||
* we can never allow a frame pointer to
|
||||
* move downwards!
|
||||
*/
|
||||
if (ebp == *(unsigned long *)ebp)
|
||||
new_ebp = *(unsigned long *)ebp;
|
||||
if (new_ebp <= ebp)
|
||||
break;
|
||||
ebp = *(unsigned long *)ebp;
|
||||
ebp = new_ebp;
|
||||
}
|
||||
#else
|
||||
while (valid_stack_ptr(tinfo, stack)) {
|
||||
|
|
Loading…
Reference in a new issue