Commit d310cbfc authored by Manfred Spraul's avatar Manfred Spraul Committed by Linus Torvalds

[PATCH] avoid crashes due to unaligned stacks

This fixes the stack end detection properly, and verifies that the
stack content printing does not overflow into the next page even
partially.

This is required especially for x86 BIOSes that misalign the stack,
together with the page access debugging that unmaps unused kernel
pages to check for valid accesses.

Architectures with special needs (eg HPPA with stacks that grow up)
can override the kernel stack end test with __HAVE_ARCH_KSTACK_END
if they ever enable the anal slab debugging code.
parent c3d6daa8
...@@ -104,7 +104,7 @@ void show_trace(struct task_struct *task, unsigned long * stack) ...@@ -104,7 +104,7 @@ void show_trace(struct task_struct *task, unsigned long * stack)
#ifdef CONFIG_KALLSYMS #ifdef CONFIG_KALLSYMS
printk("\n"); printk("\n");
#endif #endif
while (((long) stack & (THREAD_SIZE-4)) != 0) { while (!kstack_end(stack)) {
addr = *stack++; addr = *stack++;
if (kernel_text_address(addr)) { if (kernel_text_address(addr)) {
printk(" [<%08lx>] ", addr); printk(" [<%08lx>] ", addr);
...@@ -138,7 +138,7 @@ void show_stack(struct task_struct *task, unsigned long *esp) ...@@ -138,7 +138,7 @@ void show_stack(struct task_struct *task, unsigned long *esp)
stack = esp; stack = esp;
for(i = 0; i < kstack_depth_to_print; i++) { for(i = 0; i < kstack_depth_to_print; i++) {
if (((long) stack & (THREAD_SIZE-4)) == 0) if (kstack_end(stack))
break; break;
if (i && ((i % 8) == 0)) if (i && ((i % 8) == 0))
printk("\n "); printk("\n ");
......
...@@ -541,6 +541,16 @@ union thread_union { ...@@ -541,6 +541,16 @@ union thread_union {
unsigned long stack[INIT_THREAD_SIZE/sizeof(long)]; unsigned long stack[INIT_THREAD_SIZE/sizeof(long)];
}; };
#ifndef __HAVE_ARCH_KSTACK_END
static inline int kstack_end(void *addr)
{
/* Reliable end of stack detection:
* Some APM bios versions misalign the stack
*/
return !(((unsigned long)addr+sizeof(void*)-1) & (THREAD_SIZE-sizeof(void*)));
}
#endif
extern union thread_union init_thread_union; extern union thread_union init_thread_union;
extern struct task_struct init_task; extern struct task_struct init_task;
......
...@@ -862,7 +862,7 @@ static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr, unsigned ...@@ -862,7 +862,7 @@ static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr, unsigned
unsigned long *sptr = &caller; unsigned long *sptr = &caller;
unsigned long svalue; unsigned long svalue;
while (((long) sptr & (THREAD_SIZE-4)) != 0) { while (!kstack_end(sptr)) {
svalue = *sptr++; svalue = *sptr++;
if (kernel_text_address(svalue)) { if (kernel_text_address(svalue)) {
*addr++=svalue; *addr++=svalue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment