aboutsummaryrefslogtreecommitdiff
path: root/website/static/security/patches/SA-06:14/fpu4x.patch
blob: f1af32e1fc26621833da7baf4f3ede482312c65c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
Index: sys/i386/isa/npx.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/npx.c,v
retrieving revision 1.80.2.3
diff -u -I__FBSDID -r1.80.2.3 npx.c
--- sys/i386/isa/npx.c	20 Oct 2001 19:04:38 -0000	1.80.2.3
+++ sys/i386/isa/npx.c	16 Apr 2006 21:10:59 -0000
@@ -137,6 +137,10 @@
 
 typedef u_char bool_t;
 
+#ifdef CPU_ENABLE_SSE
+static	void	fpu_clean_state(void);
+#endif
+
 static	int	npx_attach	__P((device_t dev));
 	void	npx_intr	__P((void *));
 static	void	npx_identify	__P((driver_t *driver, device_t parent));
@@ -914,15 +918,49 @@
 		fnsave(addr);
 }
 
+#ifdef CPU_ENABLE_SSE
+/*
+ * On AuthenticAMD processors, the fxrstor instruction does not restore
+ * the x87's stored last instruction pointer, last data pointer, and last
+ * opcode values, except in the rare case in which the exception summary
+ * (ES) bit in the x87 status word is set to 1.
+ *
+ * In order to avoid leaking this information across processes, we clean
+ * these values by performing a dummy load before executing fxrstor().
+ */
+static	double	dummy_variable = 0.0;
+static void
+fpu_clean_state(void)
+{
+	u_short status;
+
+	/*
+	 * Clear the ES bit in the x87 status word if it is currently
+	 * set, in order to avoid causing a fault in the upcoming load.
+	 */
+	fnstsw(&status);
+	if (status & 0x80)
+		fnclex();
+
+	/*
+	 * Load the dummy variable into the x87 stack.  This mangles
+	 * the x87 stack, but we don't care since we're about to call
+	 * fxrstor() anyway.
+	 */
+	__asm __volatile("ffree %%st(7); fld %0" : : "m" (dummy_variable));
+}
+#endif /* CPU_ENABLE_SSE */
+
 static void
 fpurstor(addr)
       union savefpu *addr;
 {
 
 #ifdef CPU_ENABLE_SSE
-	if (cpu_fxsr)
+	if (cpu_fxsr) {
+		fpu_clean_state();
 		fxrstor(addr);
-	else
+	} else
 #endif
 		frstor(addr);
 }