]> err.no Git - linux-2.6/commitdiff
x86: be more careful when walking back the frame pointer chain
authorLinus Torvalds <torvalds@woody.osdl.org>
Fri, 17 Nov 2006 19:14:56 +0000 (11:14 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Fri, 17 Nov 2006 19:14:56 +0000 (11:14 -0800)
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>
arch/i386/kernel/traps.c

index 00489b706d2719c2083172342569381b60f5ce7e..fe9c5e8e7e6f5066e5f92865f0c6d71ec2887050 100644 (file)
@@ -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)) {