]> err.no Git - linux-2.6/commitdiff
[PATCH] s390: show_task oops
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Sat, 14 Jan 2006 21:20:57 +0000 (13:20 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sun, 15 Jan 2006 02:27:08 +0000 (18:27 -0800)
The show_task function walks the kernel stack backchain of processes assuming
that the processes are not running.  Since this assumption is not correct
walking the backchain can lead to an addressing exception and therefore to a
kernel hang.  So prevent the kernel hang (you still get incorrect results)
verity that all read accesses are within the bounds of the kernel stack before
performing them.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/s390/kernel/process.c

index 2ff90a1a105657afc6586fa86c5689843db66fdc..008c74526fd3344e8599e30657ad18d5e048e96b 100644 (file)
@@ -58,10 +58,18 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
  */
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-       struct stack_frame *sf;
+       struct stack_frame *sf, *low, *high;
 
-       sf = (struct stack_frame *) tsk->thread.ksp;
-       sf = (struct stack_frame *) sf->back_chain;
+       if (!tsk || !task_stack_page(tsk))
+               return 0;
+       low = task_stack_page(tsk);
+       high = (struct stack_frame *) task_pt_regs(tsk);
+       sf = (struct stack_frame *) (tsk->thread.ksp & PSW_ADDR_INSN);
+       if (sf <= low || sf > high)
+               return 0;
+       sf = (struct stack_frame *) (sf->back_chain & PSW_ADDR_INSN);
+       if (sf <= low || sf > high)
+               return 0;
        return sf->gprs[8];
 }