summaryrefslogtreecommitdiff
path: root/system/xen/xsa/xsa220-4.8.patch
diff options
context:
space:
mode:
Diffstat (limited to 'system/xen/xsa/xsa220-4.8.patch')
-rw-r--r--system/xen/xsa/xsa220-4.8.patch94
1 files changed, 94 insertions, 0 deletions
diff --git a/system/xen/xsa/xsa220-4.8.patch b/system/xen/xsa/xsa220-4.8.patch
new file mode 100644
index 0000000000..4a1ecd0d6d
--- /dev/null
+++ b/system/xen/xsa/xsa220-4.8.patch
@@ -0,0 +1,94 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86: avoid leaking PKRU and BND* between vCPU-s
+
+PKRU is explicitly "XSAVE-managed but not XSAVE-enabled", so guests
+might access the register (via {RD,WR}PKRU) without setting XCR0.PKRU.
+Force context switching as well as migrating the register as soon as
+CR4.PKE is being set the first time.
+
+For MPX (BND<n>, BNDCFGU, and BNDSTATUS) the situation is less clear,
+and the SDM has not entirely consistent information for that case.
+While experimentally the instructions don't change register state as
+long as the two XCR0 bits aren't both 1, be on the safe side and enable
+both if BNDCFGS.EN is being set the first time.
+
+This is XSA-220.
+
+Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/arch/x86/hvm/hvm.c
++++ b/xen/arch/x86/hvm/hvm.c
+@@ -311,10 +311,39 @@ int hvm_set_guest_pat(struct vcpu *v, u6
+
+ bool hvm_set_guest_bndcfgs(struct vcpu *v, u64 val)
+ {
+- return hvm_funcs.set_guest_bndcfgs &&
+- is_canonical_address(val) &&
+- !(val & IA32_BNDCFGS_RESERVED) &&
+- hvm_funcs.set_guest_bndcfgs(v, val);
++ if ( !hvm_funcs.set_guest_bndcfgs ||
++ !is_canonical_address(val) ||
++ (val & IA32_BNDCFGS_RESERVED) )
++ return false;
++
++ /*
++ * While MPX instructions are supposed to be gated on XCR0.BND*, let's
++ * nevertheless force the relevant XCR0 bits on when the feature is being
++ * enabled in BNDCFGS.
++ */
++ if ( (val & IA32_BNDCFGS_ENABLE) &&
++ !(v->arch.xcr0_accum & (XSTATE_BNDREGS | XSTATE_BNDCSR)) )
++ {
++ uint64_t xcr0 = get_xcr0();
++ int rc;
++
++ if ( v != current )
++ return false;
++
++ rc = handle_xsetbv(XCR_XFEATURE_ENABLED_MASK,
++ xcr0 | XSTATE_BNDREGS | XSTATE_BNDCSR);
++
++ if ( rc )
++ {
++ HVM_DBG_LOG(DBG_LEVEL_1, "Failed to force XCR0.BND*: %d", rc);
++ return false;
++ }
++
++ if ( handle_xsetbv(XCR_XFEATURE_ENABLED_MASK, xcr0) )
++ /* nothing, best effort only */;
++ }
++
++ return hvm_funcs.set_guest_bndcfgs(v, val);
+ }
+
+ /*
+@@ -2477,6 +2506,27 @@ int hvm_set_cr4(unsigned long value, boo
+ paging_update_paging_modes(v);
+ }
+
++ /*
++ * {RD,WR}PKRU are not gated on XCR0.PKRU and hence an oddly behaving
++ * guest may enable the feature in CR4 without enabling it in XCR0. We
++ * need to context switch / migrate PKRU nevertheless.
++ */
++ if ( (value & X86_CR4_PKE) && !(v->arch.xcr0_accum & XSTATE_PKRU) )
++ {
++ int rc = handle_xsetbv(XCR_XFEATURE_ENABLED_MASK,
++ get_xcr0() | XSTATE_PKRU);
++
++ if ( rc )
++ {
++ HVM_DBG_LOG(DBG_LEVEL_1, "Failed to force XCR0.PKRU: %d", rc);
++ goto gpf;
++ }
++
++ if ( handle_xsetbv(XCR_XFEATURE_ENABLED_MASK,
++ get_xcr0() & ~XSTATE_PKRU) )
++ /* nothing, best effort only */;
++ }
++
+ return X86EMUL_OKAY;
+
+ gpf: