summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorJoshua Elsasser <joshe@cvs.openbsd.org>2010-09-29 13:46:39 +0000
committerJoshua Elsasser <joshe@cvs.openbsd.org>2010-09-29 13:46:39 +0000
commitf26ef5b606ca0789d6e460ed12f5965ce29c596c (patch)
treec05ac2f615a2bb3a2a0ade23f3d8684fd1829758 /sys/arch
parenta1db36e23df71542df860215f73a8eab8a0f9680 (diff)
When reading MXCSR from userland sigcontext, mask out invalid bits.
This prevents a protection fault if a userland signal handler scribbles all over it's struct sigcontext Help from and ok guenther@ kettenis@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/amd64/amd64/fpu.c17
-rw-r--r--sys/arch/amd64/amd64/machdep.c9
-rw-r--r--sys/arch/amd64/amd64/process_machdep.c5
-rw-r--r--sys/arch/amd64/include/fpu.h4
-rw-r--r--sys/arch/i386/i386/machdep.c9
-rw-r--r--sys/arch/i386/i386/process_machdep.c4
-rw-r--r--sys/arch/i386/include/npx.h7
-rw-r--r--sys/arch/i386/isa/npx.c17
8 files changed, 58 insertions, 14 deletions
diff --git a/sys/arch/amd64/amd64/fpu.c b/sys/arch/amd64/amd64/fpu.c
index 832aa859789..bc1e85018d0 100644
--- a/sys/arch/amd64/amd64/fpu.c
+++ b/sys/arch/amd64/amd64/fpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fpu.c,v 1.19 2010/07/23 15:10:16 kettenis Exp $ */
+/* $OpenBSD: fpu.c,v 1.20 2010/09/29 13:46:38 joshe Exp $ */
/* $NetBSD: fpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
/*-
@@ -92,6 +92,11 @@
#define clts() __asm("clts")
#define stts() lcr0(rcr0() | CR0_TS)
+/*
+ * The mxcsr_mask for this host, taken from fxsave() on the primary CPU
+ */
+uint32_t fpu_mxcsr_mask;
+
void fpudna(struct cpu_info *);
static int x86fpflags_to_siginfo(u_int32_t);
@@ -103,6 +108,16 @@ fpuinit(struct cpu_info *ci)
{
lcr0(rcr0() & ~(CR0_EM|CR0_TS));
fninit();
+ if (CPU_IS_PRIMARY(ci)) {
+ struct fxsave64 fx __attribute__((aligned(16)));
+
+ bzero(&fx, sizeof(fx));
+ fxsave(&fx);
+ if (fx.fx_mxcsr_mask)
+ fpu_mxcsr_mask = fx.fx_mxcsr_mask;
+ else
+ fpu_mxcsr_mask = __INITIAL_MXCSR_MASK__;
+ }
lcr0(rcr0() | (CR0_TS));
}
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 44151713bcc..3790fa3f152 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.120 2010/09/21 01:04:12 matthew Exp $ */
+/* $OpenBSD: machdep.c,v 1.121 2010/09/29 13:46:38 joshe Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@@ -671,9 +671,11 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
fpusave_proc(p, 0);
if (ksc.sc_fpstate) {
- if ((error = copyin(ksc.sc_fpstate,
- &p->p_addr->u_pcb.pcb_savefpu.fp_fxsave, sizeof (struct fxsave64))))
+ struct fxsave64 *fx = &p->p_addr->u_pcb.pcb_savefpu.fp_fxsave;
+
+ if ((error = copyin(ksc.sc_fpstate, fx, sizeof(*fx))))
return (error);
+ fx->fx_mxcsr &= fpu_mxcsr_mask;
p->p_md.md_flags |= MDP_USEDFPU;
}
@@ -1211,6 +1213,7 @@ init_x86_64(paddr_t first_avail)
cpu_init_msrs(&cpu_info_primary);
+ fpuinit(&cpu_info_primary);
proc0.p_addr = proc0paddr;
cpu_info_primary.ci_curpcb = &proc0.p_addr->u_pcb;
diff --git a/sys/arch/amd64/amd64/process_machdep.c b/sys/arch/amd64/amd64/process_machdep.c
index 0a4c7a149cf..2a149487ffa 100644
--- a/sys/arch/amd64/amd64/process_machdep.c
+++ b/sys/arch/amd64/amd64/process_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: process_machdep.c,v 1.7 2010/07/23 14:56:31 kettenis Exp $ */
+/* $OpenBSD: process_machdep.c,v 1.8 2010/09/29 13:46:38 joshe Exp $ */
/* $NetBSD: process_machdep.c,v 1.1 2003/04/26 18:39:31 fvdl Exp $ */
/*-
@@ -137,7 +137,7 @@ process_read_fpregs(struct proc *p, struct fpreg *regs)
frame->fx_fsw = 0x0000;
frame->fx_ftw = 0xff;
frame->fx_mxcsr = __INITIAL_MXCSR__;
- frame->fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;
+ frame->fx_mxcsr_mask = fpu_mxcsr_mask;
p->p_md.md_flags |= MDP_USEDFPU;
}
@@ -198,6 +198,7 @@ process_write_fpregs(struct proc *p, struct fpreg *regs)
}
memcpy(frame, &regs->fxstate, sizeof(*regs));
+ frame->fx_mxcsr &= fpu_mxcsr_mask;
return (0);
}
diff --git a/sys/arch/amd64/include/fpu.h b/sys/arch/amd64/include/fpu.h
index 69f77ee812f..6b921945152 100644
--- a/sys/arch/amd64/include/fpu.h
+++ b/sys/arch/amd64/include/fpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: fpu.h,v 1.4 2010/06/29 21:13:43 thib Exp $ */
+/* $OpenBSD: fpu.h,v 1.5 2010/09/29 13:46:38 joshe Exp $ */
/* $NetBSD: fpu.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */
#ifndef _AMD64_FPU_H_
@@ -49,6 +49,8 @@ struct savefpu {
struct trapframe;
struct cpu_info;
+extern uint32_t fpu_mxcsr_mask;
+
void fpuinit(struct cpu_info *);
void fpudrop(void);
void fpudiscard(struct proc *);
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index 1f0818edcc1..940359f4f7a 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.481 2010/08/05 21:10:09 deraadt Exp $ */
+/* $OpenBSD: machdep.c,v 1.482 2010/09/29 13:46:38 joshe Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -2362,9 +2362,12 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
npxsave_proc(p, 0);
if (context.sc_fpstate) {
- if ((error = copyin(context.sc_fpstate,
- &p->p_addr->u_pcb.pcb_savefpu, sizeof (union savefpu))))
+ union savefpu *sfp = &p->p_addr->u_pcb.pcb_savefpu;
+
+ if ((error = copyin(context.sc_fpstate, sfp, sizeof(*sfp))))
return (error);
+ if (i386_use_fxsave)
+ sfp->sv_xmm.sv_env.en_mxcsr &= fpu_mxcsr_mask;
p->p_md.md_flags |= MDP_USEDFPU;
}
diff --git a/sys/arch/i386/i386/process_machdep.c b/sys/arch/i386/i386/process_machdep.c
index d5cb14f6017..3a8146edaa6 100644
--- a/sys/arch/i386/i386/process_machdep.c
+++ b/sys/arch/i386/i386/process_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: process_machdep.c,v 1.23 2010/07/23 14:56:31 kettenis Exp $ */
+/* $OpenBSD: process_machdep.c,v 1.24 2010/09/29 13:46:38 joshe Exp $ */
/* $NetBSD: process_machdep.c,v 1.22 1996/05/03 19:42:25 christos Exp $ */
/*
@@ -137,6 +137,7 @@ process_fninit_xmm(struct savexmm *sxmm)
memset(sxmm, 0, sizeof(*sxmm));
sxmm->sv_env.en_cw = __OpenBSD_NPXCW__;
sxmm->sv_env.en_mxcsr = __INITIAL_MXCSR__;
+ sxmm->sv_env.en_mxcsr_mask = fpu_mxcsr_mask;
sxmm->sv_env.en_sw = 0x0000;
sxmm->sv_env.en_tw = 0x00;
}
@@ -308,6 +309,7 @@ process_write_fpregs(struct proc *p, struct fpreg *regs)
/* XXX Yuck. */
memcpy(&s87, regs, sizeof(*regs));
process_s87_to_xmm(&s87, &frame->sv_xmm);
+ frame->sv_xmm.sv_env.en_mxcsr &= fpu_mxcsr_mask;
} else
memcpy(&frame->sv_87, regs, sizeof(*regs));
diff --git a/sys/arch/i386/include/npx.h b/sys/arch/i386/include/npx.h
index 109fb7d477a..44c26da86cd 100644
--- a/sys/arch/i386/include/npx.h
+++ b/sys/arch/i386/include/npx.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: npx.h,v 1.13 2010/07/01 17:30:27 tedu Exp $ */
+/* $OpenBSD: npx.h,v 1.14 2010/09/29 13:46:38 joshe Exp $ */
/* $NetBSD: npx.h,v 1.11 1994/10/27 04:16:11 cgd Exp $ */
/*-
@@ -96,7 +96,7 @@ struct envxmm {
uint16_t en_fos; /* FPU Data pointer selector */
uint16_t en_rsvd2;
uint32_t en_mxcsr; /* MXCSR Register State */
- uint32_t en_rsvd3;
+ uint32_t en_mxcsr_mask; /* Mask for valid MXCSR bits (may be 0) */
};
/* FPU regsters in the extended save format. */
@@ -142,6 +142,7 @@ struct emcsts {
* Set Reference, pg. 3-369.
*/
#define __INITIAL_MXCSR__ 0x1f80
+#define __INITIAL_MXCSR_MASK__ 0xffbf
/*
* The standard control word from finit is 0x37F, giving:
@@ -158,6 +159,8 @@ void process_s87_to_xmm(const struct save87 *, struct savexmm *);
struct cpu_info;
struct trapframe;
+extern uint32_t fpu_mxcsr_mask;
+
void npxinit(struct cpu_info *);
void npxtrap(struct trapframe *);
void fpu_kernel_enter(void);
diff --git a/sys/arch/i386/isa/npx.c b/sys/arch/i386/isa/npx.c
index 71c772443c1..f7a45535f91 100644
--- a/sys/arch/i386/isa/npx.c
+++ b/sys/arch/i386/isa/npx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: npx.c,v 1.51 2010/07/23 15:10:16 kettenis Exp $ */
+/* $OpenBSD: npx.c,v 1.52 2010/09/29 13:46:38 joshe Exp $ */
/* $NetBSD: npx.c,v 1.57 1996/05/12 23:12:24 mycroft Exp $ */
#if 0
@@ -97,6 +97,11 @@
#define clts() __asm("clts")
#define stts() lcr0(rcr0() | CR0_TS)
+/*
+ * The mxcsr_mask for this host, taken from fxsave() on the primary CPU
+ */
+uint32_t fpu_mxcsr_mask;
+
int npxintr(void *);
static int npxprobe1(struct isa_attach_args *);
static int x86fpflags_to_siginfo(u_int32_t);
@@ -351,6 +356,16 @@ npxinit(struct cpu_info *ci)
printf("%s: WARNING: Pentium FDIV bug detected!\n",
ci->ci_dev.dv_xname);
}
+ if (CPU_IS_PRIMARY(ci) && i386_use_fxsave) {
+ struct savexmm xm __attribute__((aligned(16)));
+
+ bzero(&xm, sizeof(xm));
+ fxsave(&xm);
+ if (xm.sv_env.en_mxcsr_mask)
+ fpu_mxcsr_mask = xm.sv_env.en_mxcsr_mask;
+ else
+ fpu_mxcsr_mask = __INITIAL_MXCSR_MASK__;
+ }
lcr0(rcr0() | (CR0_TS));
}