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;
openSUSE Build Service is sponsored by