diff options
author | Jan Beulich <jbeulich@suse.com> | 2013-09-25 10:41:25 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2013-09-25 10:41:25 +0200 |
commit | 63a75ba0de817d6f384f96d25427a05c313e2179 (patch) | |
tree | 04152e1333dc64d701f4f0107832b70cc297ca31 /xen | |
parent | 5fc2176d9b3c5988c041fa5926fdd2da2ad560b9 (diff) | |
download | xen-63a75ba0de817d6f384f96d25427a05c313e2179.tar.gz xen-63a75ba0de817d6f384f96d25427a05c313e2179.tar.bz2 xen-63a75ba0de817d6f384f96d25427a05c313e2179.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>
Diffstat (limited to 'xen')
-rw-r--r-- | xen/arch/x86/xstate.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c index c6b8dcc993..9e74929202 100644 --- a/xen/arch/x86/xstate.c +++ b/xen/arch/x86/xstate.c @@ -346,6 +346,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; @@ -359,9 +360,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; } |