File xsa456-4.patch of Package xen.36400
# Commit 62a1106415c5e8a49b45147ca84d54a58d471343
# Date 2024-04-09 16:37:30 +0100
# Author Andrew Cooper <andrew.cooper3@citrix.com>
# Committer Andrew Cooper <andrew.cooper3@citrix.com>
x86/spec-ctrl: Support BHI_DIS_S in order to mitigate BHI
Introduce a "bhi-dis-s" boolean to match the other options we have for
MSR_SPEC_CTRL values. Also introduce bhi_calculations().
Use BHI_DIS_S whenever possible.
Guests which are levelled to be migration compatible with older CPUs can't see
BHI_DIS_S, and Xen must fill in the difference to make the guest safe. Use
the virt MSR_SPEC_CTRL infrastructure to force BHI_DIS_S behind the guest's
back.
This is part of XSA-456 / CVE-2024-2201.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -2053,7 +2053,8 @@ By default SSBD will be mitigated at run
> {msr-sc,rsb,verw,ibpb-entry}=<bool>|{pv,hvm}=<bool>,
> bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,psfd,
> eager-fpu,l1d-flush,branch-harden,srb-lock,
-> unpriv-mmio,gds-mit,div-scrub,lock-harden}=<bool> ]`
+> unpriv-mmio,gds-mit,div-scrub,lock-harden,
+> bhi-dis-s}=<bool> ]`
Controls for speculative execution sidechannel mitigations. By default, Xen
will pick the most appropriate mitigations based on compiled in support,
@@ -2132,6 +2133,11 @@ option can be used to force or prevent X
default, Xen will not use PSFD. PSFD is implied by SSBD, and SSBD is off by
default.
+On hardware supporting BHI_DIS_S (Branch History Injection Disable
+Supervisor), the `bhi-dis-s=` option can be used to force or prevent Xen using
+the feature itself. By default Xen will use BHI_DIS_S on hardware susceptible
+to Branch History Injection.
+
On hardware supporting IBPB (Indirect Branch Prediction Barrier), the `ibpb=`
option can be used to force (the default) or prevent Xen from issuing branch
prediction barriers on vcpu context switches.
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -57,6 +57,7 @@
#include <asm/event.h>
#include <asm/mce.h>
#include <asm/monitor.h>
+#include <asm/spec_ctrl.h>
#include <public/arch-x86/cpuid.h>
static bool_t __initdata opt_force_ept;
@@ -568,7 +569,6 @@ static void vmx_cpuid_policy_changed(str
vmx_vmcs_enter(v);
vmx_update_exception_bitmap(v);
- vmx_vmcs_exit(v);
/*
* We can safely pass MSR_SPEC_CTRL through to the guest, even if STIBP
@@ -583,6 +583,22 @@ static void vmx_cpuid_policy_changed(str
else
vmx_set_msr_intercept(v, MSR_SPEC_CTRL, VMX_MSR_RW);
+ if ( cpu_has_vmx_virt_spec_ctrl )
+ {
+ /*
+ * If we're on BHI_DIS_S capable hardware, the short loop sequence is
+ * not sufficient to mitigate Native-BHI. If the VM can't see it
+ * (i.e. it's levelled with older hardware), force it behind the
+ * guests back for safey.
+ *
+ * Because there's not a real Host/Guest split of the MSR_SPEC_CTRL
+ * value, this only works as expected when Xen is using BHI_DIS_S too.
+ */
+ bool force_bhi_dis_s = opt_bhi_dis_s && !cp->feat.bhi_ctrl;
+
+ __vmwrite(SPEC_CTRL_MASK, force_bhi_dis_s ? SPEC_CTRL_BHI_DIS_S : 0);
+ }
+
/* MSR_PRED_CMD is safe to pass through if the guest knows about it. */
if ( cp->feat.ibrsb || cp->extd.ibpb )
vmx_clear_msr_intercept(v, MSR_PRED_CMD, VMX_MSR_RW);
@@ -594,6 +610,8 @@ static void vmx_cpuid_policy_changed(str
vmx_clear_msr_intercept(v, MSR_FLUSH_CMD, VMX_MSR_RW);
else
vmx_set_msr_intercept(v, MSR_FLUSH_CMD, VMX_MSR_RW);
+
+ vmx_vmcs_exit(v);
}
int vmx_guest_x86_mode(struct vcpu *v)
--- a/xen/arch/x86/spec_ctrl.c
+++ b/xen/arch/x86/spec_ctrl.c
@@ -58,6 +58,7 @@ static int8_t __initdata opt_ibrs = -1;
int8_t __initdata opt_stibp = -1;
bool __read_mostly opt_ssbd;
int8_t __initdata opt_psfd = -1;
+int8_t __read_mostly opt_bhi_dis_s = -1;
int8_t __read_mostly opt_ibpb_ctxt_switch = -1;
int8_t __read_mostly opt_eager_fpu = -1;
@@ -274,6 +275,8 @@ static int __init parse_spec_ctrl(const
opt_ssbd = val;
else if ( (val = parse_boolean("psfd", s, ss)) >= 0 )
opt_psfd = val;
+ else if ( (val = parse_boolean("bhi-dis-s", s, ss)) >= 0 )
+ opt_bhi_dis_s = val;
/* Misc settings. */
else if ( (val = parse_boolean("ibpb", s, ss)) >= 0 )
@@ -501,7 +504,7 @@ static void __init print_details(enum in
"\n");
/* Settings for Xen's protection, irrespective of guests. */
- printk(" Xen settings: BTI-Thunk %s, SPEC_CTRL: %s%s%s%s%s, Other:%s%s%s%s%s%s%s\n",
+ printk(" Xen settings: BTI-Thunk %s, SPEC_CTRL: %s%s%s%s%s%s, Other:%s%s%s%s%s%s%s\n",
thunk == THUNK_NONE ? "N/A" :
thunk == THUNK_RETPOLINE ? "RETPOLINE" :
thunk == THUNK_LFENCE ? "LFENCE" :
@@ -517,6 +520,8 @@ static void __init print_details(enum in
(default_xen_spec_ctrl & SPEC_CTRL_SSBD) ? " SSBD+" : " SSBD-",
!boot_cpu_has(X86_FEATURE_PSFD) &&
(default_xen_spec_ctrl & SPEC_CTRL_PSFD) ? " PSFD+" : " PSFD-",
+ !boot_cpu_has(X86_FEATURE_BHI_CTRL) ? "" :
+ (default_xen_spec_ctrl & SPEC_CTRL_BHI_DIS_S) ? " BHI_DIS_S+" : " BHI_DIS_S-",
!(caps & ARCH_CAPS_TSX_CTRL) ? "" :
(opt_tsx & 1) ? " TSX+" : " TSX-",
!cpu_has_srbds_ctrl ? "" :
@@ -1535,6 +1540,21 @@ static void __init gds_calculations(void
}
}
+/*
+ * https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/branch-history-injection.html
+ */
+static void __init bhi_calculations(void)
+{
+ if ( opt_bhi_dis_s == -1 )
+ opt_bhi_dis_s = !boot_cpu_has(X86_FEATURE_BHI_NO);
+
+ if ( !boot_cpu_has(X86_FEATURE_BHI_CTRL) )
+ opt_bhi_dis_s = false;
+
+ if ( opt_bhi_dis_s )
+ default_xen_spec_ctrl |= SPEC_CTRL_BHI_DIS_S;
+}
+
void spec_ctrl_init_domain(struct domain *d)
{
bool pv = is_pv_domain(d);
@@ -1988,6 +2008,8 @@ void __init init_speculation_mitigations
gds_calculations();
+ bhi_calculations();
+
print_details(thunk);
/*
--- a/xen/include/asm-x86/spec_ctrl.h
+++ b/xen/include/asm-x86/spec_ctrl.h
@@ -89,6 +89,7 @@ static always_inline void spec_ctrl_new_
extern int8_t opt_ibpb_ctxt_switch;
extern bool opt_ssbd;
+extern int8_t opt_bhi_dis_s;
extern int8_t opt_eager_fpu;
extern int8_t opt_l1d_flush;
extern bool opt_branch_harden;