aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2013-09-25 10:54:30 +0200
committerJan Beulich <jbeulich@suse.com>2013-09-25 10:54:30 +0200
commit945b86cb98713cd6039de14597d1bd11bae58314 (patch)
treeab8fb6a30a7bcf0aaa50e07f6219e3924ea23520
parentd4d9332a1c3fbd3f1802ffb24a95429cfc1512ed (diff)
downloadxen-945b86cb98713cd6039de14597d1bd11bae58314.tar.gz
xen-945b86cb98713cd6039de14597d1bd11bae58314.tar.bz2
xen-945b86cb98713cd6039de14597d1bd11bae58314.zip
x86/xsave: initialize extended register state when guests enable it
Till now, when setting previously unset bits in XCR0 we wouldn't touch the active register state, thus leaving in the newly enabled registers whatever a prior user of it left there, i.e. potentially leaking information between guests. This is CVE-2013-1442 / XSA-62. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> master commit: 63a75ba0de817d6f384f96d25427a05c313e2179 master date: 2013-09-25 10:41:25 +0200
-rw-r--r--xen/arch/x86/xstate.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c
index a64a832998..1cc3e375d0 100644
--- a/xen/arch/x86/xstate.c
+++ b/xen/arch/x86/xstate.c
@@ -342,6 +342,7 @@ int validate_xstate(u64 xcr0, u64 xcr0_accum, u64 xstate_bv, u64 xfeat_mask)
int handle_xsetbv(u32 index, u64 new_bv)
{
struct vcpu *curr = current;
+ u64 mask;
if ( index != XCR_XFEATURE_ENABLED_MASK )
return -EOPNOTSUPP;
@@ -355,9 +356,23 @@ int handle_xsetbv(u32 index, u64 new_bv)
if ( !set_xcr0(new_bv) )
return -EFAULT;
+ mask = new_bv & ~curr->arch.xcr0_accum;
curr->arch.xcr0 = new_bv;
curr->arch.xcr0_accum |= new_bv;
+ mask &= curr->fpu_dirtied ? ~XSTATE_FP_SSE : XSTATE_NONLAZY;
+ if ( mask )
+ {
+ unsigned long cr0 = read_cr0();
+
+ clts();
+ if ( curr->fpu_dirtied )
+ asm ( "stmxcsr %0" : "=m" (curr->arch.xsave_area->fpu_sse.mxcsr) );
+ xrstor(curr, mask);
+ if ( cr0 & X86_CR0_TS )
+ write_cr0(cr0);
+ }
+
return 0;
}