From 7632a8dc911231b0692956cb598fda56c577a617 Mon Sep 17 00:00:00 2001 From: kettenis Date: Fri, 23 Jul 2010 14:56:31 +0000 Subject: [PATCH] Don't leak the contents of the FPU and SSE registers between processes. ok deraadt@ --- sys/arch/amd64/amd64/fpu.c | 13 +++++++++---- sys/arch/amd64/amd64/machdep.c | 10 ++-------- sys/arch/amd64/amd64/process_machdep.c | 20 +++++--------------- sys/arch/i386/i386/machdep.c | 16 ++-------------- sys/arch/i386/i386/process_machdep.c | 22 ++++------------------ sys/arch/i386/isa/npx.c | 25 ++++++++++++++++--------- 6 files changed, 38 insertions(+), 68 deletions(-) diff --git a/sys/arch/amd64/amd64/fpu.c b/sys/arch/amd64/amd64/fpu.c index fdc075365f1..9da2313356e 100644 --- a/sys/arch/amd64/amd64/fpu.c +++ b/sys/arch/amd64/amd64/fpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fpu.c,v 1.17 2010/07/21 14:08:09 kettenis Exp $ */ +/* $OpenBSD: fpu.c,v 1.18 2010/07/23 14:56:31 kettenis Exp $ */ /* $NetBSD: fpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */ /*- @@ -188,6 +188,7 @@ x86fpflags_to_siginfo(u_int32_t flags) void fpudna(struct cpu_info *ci) { + struct savefpu *sfp; struct proc *p; int s; @@ -235,10 +236,14 @@ fpudna(struct cpu_info *ci) p->p_addr->u_pcb.pcb_fpcpu = ci; splx(s); + sfp = &p->p_addr->u_pcb.pcb_savefpu; + if ((p->p_md.md_flags & MDP_USEDFPU) == 0) { fninit(); - fldcw(&p->p_addr->u_pcb.pcb_savefpu.fp_fxsave.fx_fcw); - ldmxcsr(&p->p_addr->u_pcb.pcb_savefpu.fp_fxsave.fx_mxcsr); + bzero(&sfp->fp_fxsave, sizeof(sfp->fp_fxsave)); + sfp->fp_fxsave.fx_fcw = __INITIAL_NPXCW__; + sfp->fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__; + fxrstor(&sfp->fp_fxsave); p->p_md.md_flags |= MDP_USEDFPU; } else { static double zero = 0.0; @@ -249,7 +254,7 @@ fpudna(struct cpu_info *ci) */ fnclex(); __asm __volatile("ffree %%st(7)\n\tfld %0" : : "m" (zero)); - fxrstor(&p->p_addr->u_pcb.pcb_savefpu); + fxrstor(sfp); } } diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index c5f43e2a996..006753725d4 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.116 2010/07/01 23:06:33 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.117 2010/07/23 14:56:31 kettenis Exp $ */ /* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */ /*- @@ -550,7 +550,6 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, union sigval val) { struct proc *p = curproc; - struct savefpu *sfp = &p->p_addr->u_pcb.pcb_savefpu; struct trapframe *tf = p->p_md.md_regs; struct sigacts * psp = p->p_sigacts; struct sigcontext ksc; @@ -590,8 +589,6 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, /* Signal handlers get a completely clean FP state */ p->p_md.md_flags &= ~MDP_USEDFPU; - sfp->fp_fxsave.fx_fcw = __INITIAL_NPXCW__; - sfp->fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__; } sip = 0; @@ -1010,12 +1007,9 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack, /* If we were using the FPU, forget about it. */ if (p->p_addr->u_pcb.pcb_fpcpu != NULL) fpusave_proc(p, 0); - p->p_md.md_flags &= ~MDP_USEDFPU; + pcb->pcb_flags = 0; - pcb->pcb_savefpu.fp_fxsave.fx_fcw = __INITIAL_NPXCW__; - pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__; - pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; tf = p->p_md.md_regs; tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL); diff --git a/sys/arch/amd64/amd64/process_machdep.c b/sys/arch/amd64/amd64/process_machdep.c index 545280253bd..0a4c7a149cf 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.6 2008/06/26 05:42:09 ray Exp $ */ +/* $OpenBSD: process_machdep.c,v 1.7 2010/07/23 14:56:31 kettenis Exp $ */ /* $NetBSD: process_machdep.c,v 1.1 2003/04/26 18:39:31 fvdl Exp $ */ /*- @@ -131,23 +131,13 @@ process_read_fpregs(struct proc *p, struct fpreg *regs) if (p->p_md.md_flags & MDP_USEDFPU) { fpusave_proc(p, 1); } else { - u_int16_t cw; - u_int32_t mxcsr, mxcsr_mask; - - /* - * Fake a FNINIT. - * The initial control word was already set by setregs(), so - * save it temporarily. - */ - cw = frame->fx_fcw; - mxcsr = frame->fx_mxcsr; - mxcsr_mask = frame->fx_mxcsr_mask; + /* Fake a FNINIT. */ memset(frame, 0, sizeof(*regs)); - frame->fx_fcw = cw; + frame->fx_fcw = __INITIAL_NPXCW__; frame->fx_fsw = 0x0000; frame->fx_ftw = 0xff; - frame->fx_mxcsr = mxcsr; - frame->fx_mxcsr_mask = mxcsr_mask; + frame->fx_mxcsr = __INITIAL_MXCSR__; + frame->fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; p->p_md.md_flags |= MDP_USEDFPU; } diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 86faadd6e65..af304a22335 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.478 2010/07/05 22:20:22 tedu Exp $ */ +/* $OpenBSD: machdep.c,v 1.479 2010/07/23 14:56:31 kettenis Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -2179,7 +2179,6 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, union sigval val) { struct proc *p = curproc; - union savefpu *sfp = &p->p_addr->u_pcb.pcb_savefpu; struct trapframe *tf = p->p_md.md_regs; struct sigframe *fp, frame; struct sigacts *psp = p->p_sigacts; @@ -2213,11 +2212,6 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, /* Signal handlers get a completely clean FP state */ p->p_md.md_flags &= ~MDP_USEDFPU; - if (i386_use_fxsave) { - sfp->sv_xmm.sv_env.en_cw = __OpenBSD_NPXCW__; - sfp->sv_xmm.sv_env.en_mxcsr = __INITIAL_MXCSR__; - } else - sfp->sv_87.sv_env.en_cw = __OpenBSD_NPXCW__; } fp = (struct sigframe *)sp - 1; @@ -2696,6 +2690,7 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack, /* If we were using the FPU, forget about it. */ if (pcb->pcb_fpcpu != NULL) npxsave_proc(p, 0); + p->p_md.md_flags &= ~MDP_USEDFPU; #endif #ifdef USER_LDT @@ -2721,13 +2716,6 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack, */ pmap->pm_hiexec = 0; - p->p_md.md_flags &= ~MDP_USEDFPU; - if (i386_use_fxsave) { - pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = __OpenBSD_NPXCW__; - pcb->pcb_savefpu.sv_xmm.sv_env.en_mxcsr = __INITIAL_MXCSR__; - } else - pcb->pcb_savefpu.sv_87.sv_env.en_cw = __OpenBSD_NPXCW__; - tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_gs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); diff --git a/sys/arch/i386/i386/process_machdep.c b/sys/arch/i386/i386/process_machdep.c index bac70649d09..d5cb14f6017 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.22 2007/05/08 20:26:54 deraadt Exp $ */ +/* $OpenBSD: process_machdep.c,v 1.23 2010/07/23 14:56:31 kettenis Exp $ */ /* $NetBSD: process_machdep.c,v 1.22 1996/05/03 19:42:25 christos Exp $ */ /* @@ -134,17 +134,9 @@ process_xmm_to_s87(const struct savexmm *sxmm, struct save87 *s87) void process_fninit_xmm(struct savexmm *sxmm) { - /* - * The initial control word was already set by setregs(), so - * save it temporarily. - */ - uint32_t mxcsr = sxmm->sv_env.en_mxcsr; - uint16_t cw = sxmm->sv_env.en_cw; - - /* XXX Don't zero XMM regs? */ memset(sxmm, 0, sizeof(*sxmm)); - sxmm->sv_env.en_cw = cw; - sxmm->sv_env.en_mxcsr = mxcsr; + sxmm->sv_env.en_cw = __OpenBSD_NPXCW__; + sxmm->sv_env.en_mxcsr = __INITIAL_MXCSR__; sxmm->sv_env.en_sw = 0x0000; sxmm->sv_env.en_tw = 0x00; } @@ -199,14 +191,8 @@ process_read_fpregs(struct proc *p, struct fpreg *regs) if (i386_use_fxsave) { process_fninit_xmm(&frame->sv_xmm); } else { - /* - * The initial control word was already set by - * setregs(), so save it temporarily. - */ - uint16_t cw = frame->sv_87.sv_env.en_cw; - memset(&frame->sv_87, 0, sizeof(frame->sv_87)); - frame->sv_87.sv_env.en_cw = cw; + frame->sv_87.sv_env.en_cw = __OpenBSD_NPXCW__; frame->sv_87.sv_env.en_sw = 0x0000; frame->sv_87.sv_env.en_tw = 0xffff; } diff --git a/sys/arch/i386/isa/npx.c b/sys/arch/i386/isa/npx.c index 5f8c73defaf..7bc894beaf6 100644 --- a/sys/arch/i386/isa/npx.c +++ b/sys/arch/i386/isa/npx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npx.c,v 1.49 2010/07/21 14:08:09 kettenis Exp $ */ +/* $OpenBSD: npx.c,v 1.50 2010/07/23 14:56:31 kettenis Exp $ */ /* $NetBSD: npx.c,v 1.57 1996/05/12 23:12:24 mycroft Exp $ */ #if 0 @@ -600,7 +600,7 @@ x86fpflags_to_siginfo(u_int32_t flags) int npxdna_xmm(struct cpu_info *ci) { - union savefpu *addr; + union savefpu *sfp; struct proc *p; int s; @@ -657,12 +657,13 @@ npxdna_xmm(struct cpu_info *ci) splx(s); uvmexp.fpswtch++; - addr = &p->p_addr->u_pcb.pcb_savefpu; + sfp = &p->p_addr->u_pcb.pcb_savefpu; if ((p->p_md.md_flags & MDP_USEDFPU) == 0) { - fldcw(&addr->sv_xmm.sv_env.en_cw); - if (i386_has_sse || i386_has_sse2) - ldmxcsr(&addr->sv_xmm.sv_env.en_mxcsr); + bzero(&sfp->sv_xmm, sizeof(sfp->sv_xmm)); + sfp->sv_xmm.sv_env.en_cw = __OpenBSD_NPXCW__; + sfp->sv_xmm.sv_env.en_mxcsr = __INITIAL_MXCSR__; + fxrstor(&sfp->sv_xmm); p->p_md.md_flags |= MDP_USEDFPU; } else { static double zero = 0.0; @@ -673,7 +674,7 @@ npxdna_xmm(struct cpu_info *ci) */ fnclex(); __asm __volatile("ffree %%st(7)\n\tfld %0" : : "m" (zero)); - fxrstor(&addr->sv_xmm); + fxrstor(&sfp->sv_xmm); } return (1); @@ -682,6 +683,7 @@ npxdna_xmm(struct cpu_info *ci) int npxdna_s87(struct cpu_info *ci) { + union savefpu *sfp; struct proc *p; int s; @@ -736,8 +738,13 @@ npxdna_s87(struct cpu_info *ci) splx(s); uvmexp.fpswtch++; + sfp = &p->p_addr->u_pcb.pcb_savefpu; + if ((p->p_md.md_flags & MDP_USEDFPU) == 0) { - fldcw(&p->p_addr->u_pcb.pcb_savefpu.sv_87.sv_env.en_cw); + bzero(&sfp->sv_87, sizeof(sfp->sv_87)); + sfp->sv_87.sv_env.en_cw = __OpenBSD_NPXCW__; + sfp->sv_87.sv_env.en_tw = 0xffff; + frstor(&sfp->sv_87); p->p_md.md_flags |= MDP_USEDFPU; } else { /* @@ -753,7 +760,7 @@ npxdna_s87(struct cpu_info *ci) * fnclex if it is the first FPU instruction after a context * switch. */ - frstor(&p->p_addr->u_pcb.pcb_savefpu.sv_87); + frstor(&sfp->sv_87); } return (1); -- 2.20.1