aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-06-08 23:02:59 -0400
committerPaul Mackerras <paulus@samba.org>2006-06-08 23:02:59 -0400
commit7c85d1f9d358b24c5b05c3a2783a78423775a080 (patch)
tree71f92966cba279120cb81965cb3a5294295413ba /arch
parent1def630a6a49dda5bc89dfbd86656293640456f0 (diff)
powerpc: Fix machine check problem on 32-bit kernels
This fixes a bug found by Dave Jones that means that it is possible for userspace to provoke a machine check on 32-bit kernels. This also fixes a couple of other places where I found similar problems by inspection. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/signal_32.c11
-rw-r--r--arch/powerpc/kernel/signal_64.c2
2 files changed, 12 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 01e3c08cb550..8fdeca2d4597 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -803,10 +803,13 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int
803 if (__get_user(cmcp, &ucp->uc_regs)) 803 if (__get_user(cmcp, &ucp->uc_regs))
804 return -EFAULT; 804 return -EFAULT;
805 mcp = (struct mcontext __user *)(u64)cmcp; 805 mcp = (struct mcontext __user *)(u64)cmcp;
806 /* no need to check access_ok(mcp), since mcp < 4GB */
806 } 807 }
807#else 808#else
808 if (__get_user(mcp, &ucp->uc_regs)) 809 if (__get_user(mcp, &ucp->uc_regs))
809 return -EFAULT; 810 return -EFAULT;
811 if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp)))
812 return -EFAULT;
810#endif 813#endif
811 restore_sigmask(&set); 814 restore_sigmask(&set);
812 if (restore_user_regs(regs, mcp, sig)) 815 if (restore_user_regs(regs, mcp, sig))
@@ -908,13 +911,14 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
908{ 911{
909 struct sig_dbg_op op; 912 struct sig_dbg_op op;
910 int i; 913 int i;
914 unsigned char tmp;
911 unsigned long new_msr = regs->msr; 915 unsigned long new_msr = regs->msr;
912#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) 916#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
913 unsigned long new_dbcr0 = current->thread.dbcr0; 917 unsigned long new_dbcr0 = current->thread.dbcr0;
914#endif 918#endif
915 919
916 for (i=0; i<ndbg; i++) { 920 for (i=0; i<ndbg; i++) {
917 if (__copy_from_user(&op, dbg, sizeof(op))) 921 if (copy_from_user(&op, dbg + i, sizeof(op)))
918 return -EFAULT; 922 return -EFAULT;
919 switch (op.dbg_type) { 923 switch (op.dbg_type) {
920 case SIG_DBG_SINGLE_STEPPING: 924 case SIG_DBG_SINGLE_STEPPING:
@@ -959,6 +963,11 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
959 current->thread.dbcr0 = new_dbcr0; 963 current->thread.dbcr0 = new_dbcr0;
960#endif 964#endif
961 965
966 if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx))
967 || __get_user(tmp, (u8 __user *) ctx)
968 || __get_user(tmp, (u8 __user *) (ctx + 1) - 1))
969 return -EFAULT;
970
962 /* 971 /*
963 * If we get a fault copying the context into the kernel's 972 * If we get a fault copying the context into the kernel's
964 * image of the user's registers, we can't just return -EFAULT 973 * image of the user's registers, we can't just return -EFAULT
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 27f65b95184d..c2db642f4cdd 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -182,6 +182,8 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
182 err |= __get_user(msr, &sc->gp_regs[PT_MSR]); 182 err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
183 if (err) 183 if (err)
184 return err; 184 return err;
185 if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128)))
186 return -EFAULT;
185 /* Copy 33 vec registers (vr0..31 and vscr) from the stack */ 187 /* Copy 33 vec registers (vr0..31 and vscr) from the stack */
186 if (v_regs != 0 && (msr & MSR_VEC) != 0) 188 if (v_regs != 0 && (msr & MSR_VEC) != 0)
187 err |= __copy_from_user(current->thread.vr, v_regs, 189 err |= __copy_from_user(current->thread.vr, v_regs,