summaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2006-01-14 13:20:57 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-14 18:27:08 -0800
commiteb33c190c2b633f0dfc98481ecf12f62a02c705e (patch)
treecb7ec1168d0c9d333adc0d33012c0aefd808e58e /arch/s390
parent7ffbc9da137ef475afd5e01f72e1ce1ce49668b1 (diff)
downloadlinux-eb33c190c2b633f0dfc98481ecf12f62a02c705e.tar.gz
linux-eb33c190c2b633f0dfc98481ecf12f62a02c705e.tar.bz2
linux-eb33c190c2b633f0dfc98481ecf12f62a02c705e.zip
[PATCH] s390: show_task oops
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>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kernel/process.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 2ff90a1a1056..008c74526fd3 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -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];
}