]> xenbits.xensource.com Git - xen.git/commitdiff
x86/xsave: initialize extended register state when guests enable it
authorJan Beulich <jbeulich@suse.com>
Wed, 25 Sep 2013 08:54:30 +0000 (10:54 +0200)
committerJan Beulich <jbeulich@suse.com>
Wed, 25 Sep 2013 08:54:30 +0000 (10:54 +0200)
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

xen/arch/x86/xstate.c

index a64a8329984b43b5d95cce4e05739b5dbfb9c0db..1cc3e375d06d3065c291547bbbabb733d1759804 100644 (file)
@@ -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;
 }