]> git.hungrycats.org Git - linux/commitdiff
[PATCH] avoid crashes due to unaligned stacks
authorManfred Spraul <manfred@colorfullife.com>
Mon, 13 Oct 2003 04:43:13 +0000 (21:43 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Mon, 13 Oct 2003 04:43:13 +0000 (21:43 -0700)
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.

arch/i386/kernel/traps.c
include/linux/sched.h
mm/slab.c

index 3687472948ecc50f0caa355fbc28cdc3511154e6..fa0f7505f1028c77b618a9e9f76f9026675e050e 100644 (file)
@@ -104,7 +104,7 @@ void show_trace(struct task_struct *task, unsigned long * stack)
 #ifdef CONFIG_KALLSYMS
        printk("\n");
 #endif
-       while (((long) stack & (THREAD_SIZE-4)) != 0) {
+       while (!kstack_end(stack)) {
                addr = *stack++;
                if (kernel_text_address(addr)) {
                        printk(" [<%08lx>] ", addr);
@@ -138,7 +138,7 @@ void show_stack(struct task_struct *task, unsigned long *esp)
 
        stack = esp;
        for(i = 0; i < kstack_depth_to_print; i++) {
-               if (((long) stack & (THREAD_SIZE-4)) == 0)
+               if (kstack_end(stack))
                        break;
                if (i && ((i % 8) == 0))
                        printk("\n       ");
index a15d95aa34b5cf4b4fc9a8fc2af1728270c57be9..4241be4f518f802cd7ab16719c7cf9efb056ac9a 100644 (file)
@@ -541,6 +541,16 @@ union thread_union {
        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 struct task_struct init_task;
 
index 1947a87227ab4e17c7e5d12b38b3bdf397915b5d..d26829eb67d949798e3b26d42c7ce52eddc6c8e7 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -862,7 +862,7 @@ static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr, unsigned
                unsigned long *sptr = &caller;
                unsigned long svalue;
 
-               while (((long) sptr & (THREAD_SIZE-4)) != 0) {
+               while (!kstack_end(sptr)) {
                        svalue = *sptr++;
                        if (kernel_text_address(svalue)) {
                                *addr++=svalue;