diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-06-02 02:22:59 -0400 |
|---|---|---|
| committer | Paul Mackerras <paulus@samba.org> | 2008-06-08 21:32:36 -0400 |
| commit | 0be234a46596cd19eb56d2cf46836de8221afb6b (patch) | |
| tree | 5752259ba499e1e0e033df1fb59b8c57521a91ba /arch/powerpc | |
| parent | efa58fbf19fb778a8ad2fd000a6dfa9c75263a37 (diff) | |
[POWERPC] Fix incorrect enabling of VMX when building signal or user context
When building a signal or a ucontext, we can incorrectly set the MSR_VEC
bit of the kernel pt_regs->msr before returning to userspace if the task
-ever- used VMX.
This can lead to funny result if that stack used it in the past, then
"lost" it (ie. it wasn't enabled after a context switch for example)
and then called get_context. It can end up with VMX enabled and the
registers containing values from some other task.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
| -rw-r--r-- | arch/powerpc/kernel/signal_64.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index faeb8f207ea4..da7c058e3731 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
| @@ -87,6 +87,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
| 87 | #ifdef CONFIG_ALTIVEC | 87 | #ifdef CONFIG_ALTIVEC |
| 88 | elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *)(((unsigned long)sc->vmx_reserve + 15) & ~0xful); | 88 | elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *)(((unsigned long)sc->vmx_reserve + 15) & ~0xful); |
| 89 | #endif | 89 | #endif |
| 90 | unsigned long msr = regs->msr; | ||
| 90 | long err = 0; | 91 | long err = 0; |
| 91 | 92 | ||
| 92 | flush_fp_to_thread(current); | 93 | flush_fp_to_thread(current); |
| @@ -102,7 +103,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
| 102 | /* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg) | 103 | /* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg) |
| 103 | * contains valid data. | 104 | * contains valid data. |
| 104 | */ | 105 | */ |
| 105 | regs->msr |= MSR_VEC; | 106 | msr |= MSR_VEC; |
| 106 | } | 107 | } |
| 107 | /* We always copy to/from vrsave, it's 0 if we don't have or don't | 108 | /* We always copy to/from vrsave, it's 0 if we don't have or don't |
| 108 | * use altivec. | 109 | * use altivec. |
| @@ -114,6 +115,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
| 114 | err |= __put_user(&sc->gp_regs, &sc->regs); | 115 | err |= __put_user(&sc->gp_regs, &sc->regs); |
| 115 | WARN_ON(!FULL_REGS(regs)); | 116 | WARN_ON(!FULL_REGS(regs)); |
| 116 | err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); | 117 | err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); |
| 118 | err |= __put_user(msr, &sc->gp_regs[PT_MSR]); | ||
| 117 | err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); | 119 | err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); |
| 118 | err |= __put_user(signr, &sc->signal); | 120 | err |= __put_user(signr, &sc->signal); |
| 119 | err |= __put_user(handler, &sc->handler); | 121 | err |= __put_user(handler, &sc->handler); |
