From: Heiko Carstens <[email protected]>
[patch 5/13] 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 <[email protected]>
Signed-off-by: Martin Schwidefsky <[email protected]>
---
arch/s390/kernel/process.c | 15 ++++++++++++---
1 files changed, 12 insertions(+), 3 deletions(-)
diff -urpN linux-2.6/arch/s390/kernel/process.c linux-2.6-patched/arch/s390/kernel/process.c
--- linux-2.6/arch/s390/kernel/process.c 2006-01-12 15:43:19.000000000 +0100
+++ linux-2.6-patched/arch/s390/kernel/process.c 2006-01-12 15:43:55.000000000 +0100
@@ -58,10 +58,19 @@ asmlinkage void ret_from_fork(void) __as
*/
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 || !tsk->thread_info)
+ return 0;
+ low = (struct stack_frame *) tsk->thread_info;
+ high = (struct stack_frame *)
+ ((unsigned long) tsk->thread_info + THREAD_SIZE) - 1;
+ 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];
}
Martin Schwidefsky <[email protected]> wrote:
>
> From: Heiko Carstens <[email protected]>
>
> [patch 5/13] 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.
>
This one needs to be thought about and tested versus the just-merged
s390-task_stack_page.patch. I guess it'll still work, but some of the
pretty new accessors could be used in there, at least.
> --- linux-2.6/arch/s390/kernel/process.c 2006-01-12 15:43:19.000000000 +0100
> +++ linux-2.6-patched/arch/s390/kernel/process.c 2006-01-12 15:43:55.000000000 +0100
> @@ -58,10 +58,19 @@ asmlinkage void ret_from_fork(void) __as
> */
> 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 || !tsk->thread_info)
> + return 0;
> + low = (struct stack_frame *) tsk->thread_info;
> + high = (struct stack_frame *)
> + ((unsigned long) tsk->thread_info + THREAD_SIZE) - 1;
> + 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];
> }
>
On Thu, 2006-01-12 at 16:58 -0800, Andrew Morton wrote:
> Martin Schwidefsky <[email protected]> wrote:
> >
> > From: Heiko Carstens <[email protected]>
> >
> > [patch 5/13] 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.
> >
>
> This one needs to be thought about and tested versus the just-merged
> s390-task_stack_page.patch. I guess it'll still work, but some of the
> pretty new accessors could be used in there, at least.
Oh yes, didn't notice that Al Viro's task_thread_info() changes got
merged in the meantime. We'll test & send a follow-up patch.
--
blue skies,
Martin
Martin Schwidefsky
Linux for zSeries Development & Services
IBM Deutschland Entwicklung GmbH
From: Heiko Carstens <[email protected]>
Use new stack page accessors as pointed out by Andrew Morton.
Signed-off-by: Heiko Carstens <[email protected]>
---
arch/s390/kernel/process.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff -urN a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
--- a/arch/s390/kernel/process.c 2006-01-13 12:15:44.000000000 +0100
+++ b/arch/s390/kernel/process.c 2006-01-13 12:43:32.000000000 +0100
@@ -60,11 +60,10 @@
{
struct stack_frame *sf, *low, *high;
- if (!tsk || !tsk->thread_info)
+ if (!tsk || !task_stack_page(tsk))
return 0;
- low = (struct stack_frame *) tsk->thread_info;
- high = (struct stack_frame *)
- ((unsigned long) tsk->thread_info + THREAD_SIZE) - 1;
+ 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;