Don't leak the contents of the FPU and SSE registers between processes.
authorkettenis <kettenis@openbsd.org>
Fri, 23 Jul 2010 14:56:31 +0000 (14:56 +0000)
committerkettenis <kettenis@openbsd.org>
Fri, 23 Jul 2010 14:56:31 +0000 (14:56 +0000)
ok deraadt@

sys/arch/amd64/amd64/fpu.c
sys/arch/amd64/amd64/machdep.c
sys/arch/amd64/amd64/process_machdep.c
sys/arch/i386/i386/machdep.c
sys/arch/i386/i386/process_machdep.c
sys/arch/i386/isa/npx.c

index fdc0753..9da2313 100644 (file)
@@ -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);
        }
 }
 
index c5f43e2..0067537 100644 (file)
@@ -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);
index 5452802..0a4c7a1 100644 (file)
@@ -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;
        }
 
index 86faadd..af304a2 100644 (file)
@@ -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);
index bac7064..d5cb14f 100644 (file)
@@ -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;
                }
index 5f8c73d..7bc894b 100644 (file)
@@ -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);