ia64/xen-unstable
changeset 9867:4d667a139318
This patch addresses CVE-2006-1056 (information leak from
fxsave/fxrstor on AMD CPUs) and also adjusts 64-bit handling so that
full 64-bit RIP/RDP values get saved/restored. More fine-grained
handling may be needed if 32-bit processes are expected to properly
see their selectors (native Linux doesn't currently do that either,
but there is a patch to adjust it there).
Original patch: Jan Beulich (based on Linux original by Andi Kleen)
Signed-off-by: Keir Fraser <keir@xensource.com>
fxsave/fxrstor on AMD CPUs) and also adjusts 64-bit handling so that
full 64-bit RIP/RDP values get saved/restored. More fine-grained
handling may be needed if 32-bit processes are expected to properly
see their selectors (native Linux doesn't currently do that either,
but there is a patch to adjust it there).
Original patch: Jan Beulich (based on Linux original by Andi Kleen)
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Wed Apr 26 20:01:37 2006 +0100 (2006-04-26) |
parents | 1d69cff40b8c |
children | 3d884434ec97 |
files | xen/arch/x86/i387.c |
line diff
1.1 --- a/xen/arch/x86/i387.c Wed Apr 26 17:41:19 2006 +0100 1.2 +++ b/xen/arch/x86/i387.c Wed Apr 26 20:01:37 2006 +0100 1.3 @@ -26,19 +26,54 @@ void init_fpu(void) 1.4 void save_init_fpu(struct vcpu *v) 1.5 { 1.6 unsigned long cr0 = read_cr0(); 1.7 + char *fpu_ctxt = v->arch.guest_context.fpu_ctxt.x; 1.8 1.9 /* This can happen, if a paravirtualised guest OS has set its CR0.TS. */ 1.10 if ( cr0 & X86_CR0_TS ) 1.11 clts(); 1.12 1.13 if ( cpu_has_fxsr ) 1.14 + { 1.15 +#ifdef __i386__ 1.16 __asm__ __volatile__ ( 1.17 - "fxsave %0 ; fnclex" 1.18 - : "=m" (v->arch.guest_context.fpu_ctxt) ); 1.19 + "fxsave %0" 1.20 + : "=m" (*fpu_ctxt) ); 1.21 +#else /* __x86_64__ */ 1.22 + /* 1.23 + * The only way to force fxsaveq on a wide range of gas versions. On 1.24 + * older versions the rex64 prefix works only if we force an addressing 1.25 + * mode that doesn't require extended registers. 1.26 + */ 1.27 + __asm__ __volatile__ ( 1.28 + "rex64/fxsave (%1)" 1.29 + : "=m" (*fpu_ctxt) : "cdaSDb" (fpu_ctxt) ); 1.30 +#endif 1.31 + 1.32 + /* Clear exception flags if FSW.ES is set. */ 1.33 + if ( unlikely(fpu_ctxt[2] & 0x80) ) 1.34 + __asm__ __volatile__ ("fnclex"); 1.35 + 1.36 + /* 1.37 + * AMD CPUs don't save/restore FDP/FIP/FOP unless an exception 1.38 + * is pending. Clear the x87 state here by setting it to fixed 1.39 + * values. The hypervisor data segment can be sometimes 0 and 1.40 + * sometimes new user value. Both should be ok. Use the FPU saved 1.41 + * data block as a safe address because it should be in L1. 1.42 + */ 1.43 + if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) 1.44 + { 1.45 + __asm__ __volatile__ ( 1.46 + "emms\n\t" /* clear stack tags */ 1.47 + "fildl %0" /* load to clear state */ 1.48 + : : "m" (*fpu_ctxt) ); 1.49 + } 1.50 + } 1.51 else 1.52 + { 1.53 __asm__ __volatile__ ( 1.54 "fnsave %0 ; fwait" 1.55 - : "=m" (v->arch.guest_context.fpu_ctxt) ); 1.56 + : "=m" (*fpu_ctxt) ); 1.57 + } 1.58 1.59 clear_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags); 1.60 write_cr0(cr0|X86_CR0_TS); 1.61 @@ -46,14 +81,22 @@ void save_init_fpu(struct vcpu *v) 1.62 1.63 void restore_fpu(struct vcpu *v) 1.64 { 1.65 + char *fpu_ctxt = v->arch.guest_context.fpu_ctxt.x; 1.66 + 1.67 /* 1.68 * FXRSTOR can fault if passed a corrupted data block. We handle this 1.69 * possibility, which may occur if the block was passed to us by control 1.70 * tools, by silently clearing the block. 1.71 */ 1.72 if ( cpu_has_fxsr ) 1.73 + { 1.74 __asm__ __volatile__ ( 1.75 +#ifdef __i386__ 1.76 "1: fxrstor %0 \n" 1.77 +#else /* __x86_64__ */ 1.78 + /* See above for why the operands/constraints are this way. */ 1.79 + "1: rex64/fxrstor (%2) \n" 1.80 +#endif 1.81 ".section .fixup,\"ax\" \n" 1.82 "2: push %%"__OP"ax \n" 1.83 " push %%"__OP"cx \n" 1.84 @@ -72,12 +115,19 @@ void restore_fpu(struct vcpu *v) 1.85 " "__FIXUP_WORD" 1b,2b \n" 1.86 ".previous \n" 1.87 : 1.88 - : "m" (v->arch.guest_context.fpu_ctxt), 1.89 - "i" (sizeof(v->arch.guest_context.fpu_ctxt)/4) ); 1.90 + : "m" (*fpu_ctxt), 1.91 + "i" (sizeof(v->arch.guest_context.fpu_ctxt)/4) 1.92 +#ifdef __x86_64__ 1.93 + ,"cdaSDb" (fpu_ctxt) 1.94 +#endif 1.95 + ); 1.96 + } 1.97 else 1.98 + { 1.99 __asm__ __volatile__ ( 1.100 "frstor %0" 1.101 : : "m" (v->arch.guest_context.fpu_ctxt) ); 1.102 + } 1.103 } 1.104 1.105 /*