diff options
Diffstat (limited to 'system/xen/xsa/xsa190.patch')
-rw-r--r-- | system/xen/xsa/xsa190.patch | 173 |
1 files changed, 0 insertions, 173 deletions
diff --git a/system/xen/xsa/xsa190.patch b/system/xen/xsa/xsa190.patch deleted file mode 100644 index 3c242e6cc2..0000000000 --- a/system/xen/xsa/xsa190.patch +++ /dev/null @@ -1,173 +0,0 @@ -x86emul: honor guest CR0.TS and CR0.EM - -We must not emulate any instructions accessing respective registers -when either of these flags is set in the guest view of the register, or -else we may do so on data not belonging to the guest's current task. - -Being architecturally required behavior, the logic gets placed in the -instruction emulator instead of hvmemul_get_fpu(). It should be noted, -though, that hvmemul_get_fpu() being the only current handler for the -get_fpu() callback, we don't have an active problem with CR4: Both -CR4.OSFXSR and CR4.OSXSAVE get handled as necessary by that function. - -This is XSA-190. - -Signed-off-by: Jan Beulich <jbeulich@suse.com> -Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> ---- -v4: Only raise #NM on FWAIT when CR0.TS and CR0.MP are set. -v3: Correct which exception to raise upon set CR0.EM. -v2: Require the read_cr hook to be set, which then requires a change to - the test code too. ---- -The change to xen/arch/x86/hvm/emulate.c isn't strictly needed for -fixing the security issue, but the patch would be rather incomplete -without. - ---- a/tools/tests/x86_emulator/test_x86_emulator.c -+++ b/tools/tests/x86_emulator/test_x86_emulator.c -@@ -158,6 +158,22 @@ static inline uint64_t xgetbv(uint32_t x - (ebx & (1U << 5)) != 0; \ - }) - -+static int read_cr( -+ unsigned int reg, -+ unsigned long *val, -+ struct x86_emulate_ctxt *ctxt) -+{ -+ /* Fake just enough state for the emulator's _get_fpu() to be happy. */ -+ switch ( reg ) -+ { -+ case 0: -+ *val = 0x00000001; /* PE */ -+ return X86EMUL_OKAY; -+ } -+ -+ return X86EMUL_UNHANDLEABLE; -+} -+ - int get_fpu( - void (*exception_callback)(void *, struct cpu_user_regs *), - void *exception_callback_arg, -@@ -189,6 +205,7 @@ static struct x86_emulate_ops emulops = - .write = write, - .cmpxchg = cmpxchg, - .cpuid = cpuid, -+ .read_cr = read_cr, - .get_fpu = get_fpu, - }; - ---- a/xen/arch/x86/hvm/emulate.c -+++ b/xen/arch/x86/hvm/emulate.c -@@ -1628,14 +1628,14 @@ static int hvmemul_get_fpu( - switch ( type ) - { - case X86EMUL_FPU_fpu: -+ case X86EMUL_FPU_wait: - break; - case X86EMUL_FPU_mmx: - if ( !cpu_has_mmx ) - return X86EMUL_UNHANDLEABLE; - break; - case X86EMUL_FPU_xmm: -- if ( (curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_EM) || -- !(curr->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSFXSR) ) -+ if ( !(curr->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSFXSR) ) - return X86EMUL_UNHANDLEABLE; - break; - case X86EMUL_FPU_ymm: ---- a/xen/arch/x86/x86_emulate/x86_emulate.c -+++ b/xen/arch/x86/x86_emulate/x86_emulate.c -@@ -420,6 +420,9 @@ typedef union { - - /* Control register flags. */ - #define CR0_PE (1<<0) -+#define CR0_MP (1<<1) -+#define CR0_EM (1<<2) -+#define CR0_TS (1<<3) - #define CR4_TSD (1<<2) - - /* EFLAGS bit definitions. */ -@@ -447,6 +450,7 @@ typedef union { - #define EXC_OF 4 - #define EXC_BR 5 - #define EXC_UD 6 -+#define EXC_NM 7 - #define EXC_TS 10 - #define EXC_NP 11 - #define EXC_SS 12 -@@ -746,10 +750,45 @@ static void fpu_handle_exception(void *_ - regs->eip += fic->insn_bytes; - } - -+static int _get_fpu( -+ enum x86_emulate_fpu_type type, -+ struct fpu_insn_ctxt *fic, -+ struct x86_emulate_ctxt *ctxt, -+ const struct x86_emulate_ops *ops) -+{ -+ int rc; -+ -+ fic->exn_raised = 0; -+ -+ fail_if(!ops->get_fpu); -+ rc = ops->get_fpu(fpu_handle_exception, fic, type, ctxt); -+ -+ if ( rc == X86EMUL_OKAY ) -+ { -+ unsigned long cr0; -+ -+ fail_if(!ops->read_cr); -+ rc = ops->read_cr(0, &cr0, ctxt); -+ if ( rc != X86EMUL_OKAY ) -+ return rc; -+ if ( cr0 & CR0_EM ) -+ { -+ generate_exception_if(type == X86EMUL_FPU_fpu, EXC_NM, -1); -+ generate_exception_if(type == X86EMUL_FPU_mmx, EXC_UD, -1); -+ generate_exception_if(type == X86EMUL_FPU_xmm, EXC_UD, -1); -+ } -+ generate_exception_if((cr0 & CR0_TS) && -+ (type != X86EMUL_FPU_wait || (cr0 & CR0_MP)), -+ EXC_NM, -1); -+ } -+ -+ done: -+ return rc; -+} -+ - #define get_fpu(_type, _fic) \ --do{ (_fic)->exn_raised = 0; \ -- fail_if(ops->get_fpu == NULL); \ -- rc = ops->get_fpu(fpu_handle_exception, _fic, _type, ctxt); \ -+do { \ -+ rc = _get_fpu(_type, _fic, ctxt, ops); \ - if ( rc ) goto done; \ - } while (0) - #define _put_fpu() \ -@@ -2879,8 +2918,14 @@ x86_emulate( - } - - case 0x9b: /* wait/fwait */ -- emulate_fpu_insn("fwait"); -+ { -+ struct fpu_insn_ctxt fic = { .insn_bytes = 1 }; -+ -+ get_fpu(X86EMUL_FPU_wait, &fic); -+ asm volatile ( "fwait" ::: "memory" ); -+ put_fpu(&fic); - break; -+ } - - case 0x9c: /* pushf */ - src.val = _regs.eflags; ---- a/xen/arch/x86/x86_emulate/x86_emulate.h -+++ b/xen/arch/x86/x86_emulate/x86_emulate.h -@@ -115,6 +115,7 @@ struct __packed segment_register { - /* FPU sub-types which may be requested via ->get_fpu(). */ - enum x86_emulate_fpu_type { - X86EMUL_FPU_fpu, /* Standard FPU coprocessor instruction set */ -+ X86EMUL_FPU_wait, /* WAIT/FWAIT instruction */ - X86EMUL_FPU_mmx, /* MMX instruction set (%mm0-%mm7) */ - X86EMUL_FPU_xmm, /* SSE instruction set (%xmm0-%xmm7/15) */ - X86EMUL_FPU_ymm /* AVX/XOP instruction set (%ymm0-%ymm7/15) */ |