Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Jun 2006 18:53:52 GMT
From:      Rostislav Krasny <rosti.bsd@FreeBSD.org>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/98460: [PATCH] fpu_clean_state() cannot be disabled for not AMD processors, those are not vulnerable to FreeBSD-SA-06:14.fpu
Message-ID:  <200606031853.k53IrqiA015998@www.freebsd.org>
Resent-Message-ID: <200606031900.k53J0asj057293@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         98460
>Category:       kern
>Synopsis:       [PATCH] fpu_clean_state() cannot be disabled for not AMD processors, those are not vulnerable to FreeBSD-SA-06:14.fpu
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sat Jun 03 19:00:35 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Rostislav Krasny
>Release:        6.1-STABLE
>Organization:
>Environment:
>Description:
When FreeBSD is running on any non AMD processor an fpu_clean_state() function
adds unneeded operations to a context switch. My patch makes it possible
to disable the fpu_clean_state() by rebuilding a kernel with
"options CPU_FXSAVE_NO_LEAK".

Colin Percival has nothing against my idea in general:

http://lists.freebsd.org/pipermail/freebsd-current/2006-May/062683.html

and David Xu as well:

http://lists.freebsd.org/pipermail/freebsd-current/2006-May/063206.html

Following message is a beginning of that thread:

http://lists.freebsd.org/pipermail/freebsd-current/2006-April/062662.html
>How-To-Repeat:
You can use following command to check how your kernel has been builded:

objdump -x /boot/kernel/kernel | grep fpu_clean_state
>Fix:
diff -ru src/sys.orig/amd64/amd64/fpu.c src/sys/amd64/amd64/fpu.c
--- src/sys.orig/amd64/amd64/fpu.c	Wed Apr 19 10:00:35 2006
+++ src/sys/amd64/amd64/fpu.c	Sat Jun  3 21:14:06 2006
@@ -33,6 +33,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD: src/sys/amd64/amd64/fpu.c,v 1.157.2.1 2006/04/19 07:00:35 cperciva Exp $");
 
+#include "opt_cpu.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
@@ -96,7 +98,9 @@
 
 typedef u_char bool_t;
 
+#ifndef CPU_FXSAVE_NO_LEAK
 static	void	fpu_clean_state(void);
+#endif
 
 int	hw_float = 1;
 SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
@@ -409,7 +413,9 @@
 	PCPU_SET(fpcurthread, curthread);
 	pcb = PCPU_GET(curpcb);
 
+#ifndef CPU_FXSAVE_NO_LEAK
 	fpu_clean_state();
+#endif
 
 	if ((pcb->pcb_flags & PCB_FPUINITDONE) == 0) {
 		/*
@@ -478,7 +484,9 @@
 
 	s = intr_disable();
 	if (td == PCPU_GET(fpcurthread)) {
+#ifndef CPU_FXSAVE_NO_LEAK
 		fpu_clean_state();
+#endif
 		fxrstor(addr);
 		intr_restore(s);
 	} else {
@@ -488,6 +496,7 @@
 	curthread->td_pcb->pcb_flags |= PCB_FPUINITDONE;
 }
 
+#ifndef CPU_FXSAVE_NO_LEAK
 /*
  * On AuthenticAMD processors, the fxrstor instruction does not restore
  * the x87's stored last instruction pointer, last data pointer, and last
@@ -518,6 +527,7 @@
 	 */
 	__asm __volatile("ffree %%st(7); fld %0" : : "m" (dummy_variable));
 }
+#endif /* !CPU_FXSAVE_NO_LEAK */
 
 /*
  * This really sucks.  We want the acpi version only, but it requires
diff -ru src/sys.orig/amd64/conf/NOTES src/sys/amd64/conf/NOTES
--- src/sys.orig/amd64/conf/NOTES	Sun Apr 30 20:39:43 2006
+++ src/sys/amd64/conf/NOTES	Sat Jun  3 21:14:06 2006
@@ -57,6 +57,12 @@
 # Options for CPU features.
 #
 
+# CPU_FXSAVE_NO_LEAK disables security workaround of FPU registers leak by
+# FXSAVE and FXRSTOR instructions of "7th generation" and "8th generation"
+# processors manufactured by AMD. For more information read a
+# FreeBSD-SA-06:14.fpu security advisory.
+options 	CPU_FXSAVE_NO_LEAK
+
 #
 # PERFMON causes the driver for Pentium/Pentium Pro performance counters
 # to be compiled.  See perfmon(4) for more information.
diff -ru src/sys.orig/conf/options.amd64 src/sys/conf/options.amd64
--- src/sys.orig/conf/options.amd64	Thu Jun 30 02:23:16 2005
+++ src/sys/conf/options.amd64	Sat Jun  3 21:14:06 2006
@@ -49,6 +49,7 @@
 # EOF
 # -------------------------------
 HAMMER			opt_cpu.h
+CPU_FXSAVE_NO_LEAK	opt_cpu.h
 PPC_PROBE_CHIPSET	opt_ppc.h
 PPC_DEBUG		opt_ppc.h
 PSM_HOOKRESUME		opt_psm.h
diff -ru src/sys.orig/conf/options.i386 src/sys/conf/options.i386
--- src/sys.orig/conf/options.i386	Sat Jul  2 23:06:42 2005
+++ src/sys/conf/options.i386	Sat Jun  3 21:14:06 2006
@@ -52,6 +52,7 @@
 CPU_ELAN_XTAL			opt_cpu.h
 CPU_ENABLE_LONGRUN		opt_cpu.h
 CPU_FASTER_5X86_FPU		opt_cpu.h
+CPU_FXSAVE_NO_LEAK		opt_cpu.h
 CPU_GEODE			opt_cpu.h
 CPU_I486_ON_386			opt_cpu.h
 CPU_IORT			opt_cpu.h
diff -ru src/sys.orig/i386/conf/NOTES src/sys/i386/conf/NOTES
--- src/sys.orig/i386/conf/NOTES	Wed May 10 17:26:03 2006
+++ src/sys/i386/conf/NOTES	Sat Jun  3 21:14:06 2006
@@ -118,6 +118,11 @@
 #
 # CPU_FASTER_5X86_FPU enables faster FPU exception handler.
 #
+# CPU_FXSAVE_NO_LEAK disables security workaround of FPU registers leak by
+# FXSAVE and FXRSTOR instructions of "7th generation" and "8th generation"
+# processors manufactured by AMD. For more information read a
+# FreeBSD-SA-06:14.fpu security advisory.
+#
 # CPU_GEODE is for the SC1100 Geode embedded processor.  This option
 # is necessary because the i8254 timecounter is toast.
 #
@@ -192,6 +197,7 @@
 options 	CPU_ELAN_XTAL=32768000
 options 	CPU_ENABLE_LONGRUN
 options 	CPU_FASTER_5X86_FPU
+options 	CPU_FXSAVE_NO_LEAK
 options 	CPU_GEODE
 options 	CPU_I486_ON_386
 options 	CPU_IORT
diff -ru src/sys.orig/i386/isa/npx.c src/sys/i386/isa/npx.c
--- src/sys.orig/i386/isa/npx.c	Sun Apr 30 08:15:20 2006
+++ src/sys/i386/isa/npx.c	Sat Jun  3 21:14:06 2006
@@ -142,7 +142,7 @@
 
 typedef u_char bool_t;
 
-#ifdef CPU_ENABLE_SSE
+#if defined(CPU_ENABLE_SSE) && !defined(CPU_FXSAVE_NO_LEAK)
 static	void	fpu_clean_state(void);
 #endif
 
@@ -956,7 +956,7 @@
 		fnsave(addr);
 }
 
-#ifdef CPU_ENABLE_SSE
+#if defined(CPU_ENABLE_SSE) && !defined(CPU_FXSAVE_NO_LEAK)
 /*
  * On AuthenticAMD processors, the fxrstor instruction does not restore
  * the x87's stored last instruction pointer, last data pointer, and last
@@ -987,7 +987,7 @@
 	 */
 	__asm __volatile("ffree %%st(7); fld %0" : : "m" (dummy_variable));
 }
-#endif /* CPU_ENABLE_SSE */
+#endif /* CPU_ENABLE_SSE && !CPU_FXSAVE_NO_LEAK */
 
 static void
 fpurstor(addr)
@@ -996,7 +996,9 @@
 
 #ifdef CPU_ENABLE_SSE
 	if (cpu_fxsr) {
+#ifndef CPU_FXSAVE_NO_LEAK
 		fpu_clean_state();
+#endif
 		fxrstor(addr);
 	} else
 #endif

>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606031853.k53IrqiA015998>