system/xen: Added XSA-190 security advisory patch.
Signed-off-by: Mario Preksavec <mario@slackware.hr>
This commit is contained in:
parent
0fa1762f09
commit
b1a0ce4079
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
PRGNAM=xen
|
PRGNAM=xen
|
||||||
VERSION=${VERSION:-4.7.0}
|
VERSION=${VERSION:-4.7.0}
|
||||||
BUILD=${BUILD:-1}
|
BUILD=${BUILD:-2}
|
||||||
TAG=${TAG:-_SBo}
|
TAG=${TAG:-_SBo}
|
||||||
|
|
||||||
SEABIOS=${SEABIOS:-1.9.2}
|
SEABIOS=${SEABIOS:-1.9.2}
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
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) */
|
Loading…
Reference in New Issue