On Fri, 31 Aug 2007, Rusty Russell wrote:Fair enough. That said, you seem to see this even without a corrupt stack. The unwinder should stop when it sees an invalid frame pointer, and even without the push 0 I'd have expected it to be invalid. But I suspect lguest triggers another thing: you actually make the stack start at the *very*top* of the stack area. Afaik, normal x86 does not. A normal x86 kernel will start off with a pt_regs[] setup, I think - ie the kernel stack is always set up so that it has the "return to user mode" information. And *that* difference may be what triggers this for lguest, even though it can never trigger for a "real" kernel. But your patch does improve the sanity checking of the frame pointer. That said, I think the following patch improves it more: does this also work for you? (Totally untested, but it looks like the RightThing(tm) to do) Linus --- diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index cfffe3d..b9998f3 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -100,10 +100,10 @@ asmlinkage void machine_check(void); int kstack_depth_to_print = 24; static unsigned int code_bytes = 64; -static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) +static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned size) { return p > (void *)tinfo && - p < (void *)tinfo + THREAD_SIZE - 3; + p <= (void *)tinfo + THREAD_SIZE - size; } static inline unsigned long print_context_stack(struct thread_info *tinfo, @@ -113,7 +113,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, unsigned long addr; #ifdef CONFIG_FRAME_POINTER - while (valid_stack_ptr(tinfo, (void *)ebp)) { + while (valid_stack_ptr(tinfo, (void *)ebp, 2*sizeof(unsigned long))) { unsigned long new_ebp; addr = *(unsigned long *)(ebp + 4); ops->address(data, addr); @@ -129,7 +129,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, ebp = new_ebp; } #else - while (valid_stack_ptr(tinfo, stack)) { + while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) { addr = *stack++; if (__kernel_text_address(addr)) ops->address(data, addr); -
| david | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Greg Kroah-Hartman | [PATCH 004/196] Chinese: add translation of SubmittingPatches |
| Paul Jackson | Re: cpuset-remove-sched-domain-hooks-from-cpusets |
| Rafael J. Wysocki | [Bug #11210] libata badness |
| David Miller | Re: [GIT]: Networking |
| Jarek Poplawski | [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Gerrit Renker | [PATCH 27/37] dccp: Integration of dynamic feature activation - part 2 (server side) |
| Andrew Morton | Re: [BUG] New Kernel Bugs |
git: | |
