[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen stable-4.13] x86/spec-ctrl: Mitigate Branch Type Confusion when possible
commit f8614c7153f95dcd1a1320156787dbc5325fd946 Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> AuthorDate: Mon Jun 27 19:29:40 2022 +0100 Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> CommitDate: Tue Jul 12 16:33:19 2022 +0100 x86/spec-ctrl: Mitigate Branch Type Confusion when possible Branch Type Confusion affects AMD/Hygon CPUs on Zen2 and earlier. To mitigate, we require SMT safety (STIBP on Zen2, no-SMT on Zen1), and to issue an IBPB on each entry to Xen, to flush the BTB. Due to performance concerns, dom0 (which is trusted in most configurations) is excluded from protections by default. Therefore: * Use STIBP by default on Zen2 too, which now means we want it on by default on all hardware supporting STIBP. * Break the current IBPB logic out into a new function, extending it with IBPB-at-entry logic. * Change the existing IBPB-at-ctxt-switch boolean to be tristate, and disable it by default when IBPB-at-entry is providing sufficient safety. If all PV guests on the system are trusted, then it is recommended to boot with `spec-ctrl=ibpb-entry=no-pv`, as this will provide an additional marginal perf improvement. This is part of XSA-407 / CVE-2022-23825. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> (cherry picked from commit d8cb7e0f069e0f106d24941355b59b45a731eabe) --- docs/misc/xen-command-line.pandoc | 14 +++-- xen/arch/x86/spec_ctrl.c | 113 ++++++++++++++++++++++++++++++++++---- xen/include/asm-x86/spec_ctrl.h | 2 +- 3 files changed, 112 insertions(+), 17 deletions(-) diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc index 359859b518..956ecd5a35 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -2034,7 +2034,7 @@ By default SSBD will be mitigated at runtime (i.e `ssbd=runtime`). ### spec-ctrl (x86) > `= List of [ <bool>, xen=<bool>, {pv,hvm}=<bool>, -> {msr-sc,rsb,md-clear}=<bool>|{pv,hvm}=<bool>, +> {msr-sc,rsb,md-clear,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}=<bool> ]` @@ -2059,9 +2059,10 @@ in place for guests to use. Use of a positive boolean value for either of these options is invalid. -The `pv=`, `hvm=`, `msr-sc=`, `rsb=` and `md-clear=` options offer fine -grained control over the primitives by Xen. These impact Xen's ability to -protect itself, and/or Xen's ability to virtualise support for guests to use. +The `pv=`, `hvm=`, `msr-sc=`, `rsb=`, `md-clear=` and `ibpb-entry=` options +offer fine grained control over the primitives by Xen. These impact Xen's +ability to protect itself, and/or Xen's ability to virtualise support for +guests to use. * `pv=` and `hvm=` offer control over all suboptions for PV and HVM guests respectively. @@ -2080,6 +2081,11 @@ protect itself, and/or Xen's ability to virtualise support for guests to use. compatibility with development versions of this fix, `mds=` is also accepted on Xen 4.12 and earlier as an alias. Consult vendor documentation in preference to here.* +* `ibpb-entry=` offers control over whether IBPB (Indirect Branch Prediction + Barrier) is used on entry to Xen. This is used by default on hardware + vulnerable to Branch Type Confusion, but for performance reasons, dom0 is + unprotected by default. If it necessary to protect dom0 too, boot with + `spec-ctrl=ibpb-entry`. If Xen was compiled with INDIRECT_THUNK support, `bti-thunk=` can be used to select which of the thunks gets patched into the `__x86_indirect_thunk_%reg` diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c index 4fdc6e93ad..bfa5d27e00 100644 --- a/xen/arch/x86/spec_ctrl.c +++ b/xen/arch/x86/spec_ctrl.c @@ -39,6 +39,10 @@ static bool __initdata opt_rsb_hvm = true; static int8_t __read_mostly opt_md_clear_pv = -1; static int8_t __read_mostly opt_md_clear_hvm = -1; +static int8_t __read_mostly opt_ibpb_entry_pv = -1; +static int8_t __read_mostly opt_ibpb_entry_hvm = -1; +static bool __read_mostly opt_ibpb_entry_dom0; + /* Cmdline controls for Xen's speculative settings. */ static enum ind_thunk { THUNK_DEFAULT, /* Decide which thunk to use at boot time. */ @@ -54,7 +58,7 @@ int8_t __initdata opt_stibp = -1; bool __read_mostly opt_ssbd; int8_t __initdata opt_psfd = -1; -bool __read_mostly opt_ibpb_ctxt_switch = true; +int8_t __read_mostly opt_ibpb_ctxt_switch = -1; int8_t __read_mostly opt_eager_fpu = -1; int8_t __read_mostly opt_l1d_flush = -1; bool __read_mostly opt_branch_harden = true; @@ -115,6 +119,9 @@ static int __init parse_spec_ctrl(const char *s) opt_rsb_hvm = false; opt_md_clear_pv = 0; opt_md_clear_hvm = 0; + opt_ibpb_entry_pv = 0; + opt_ibpb_entry_hvm = 0; + opt_ibpb_entry_dom0 = false; opt_thunk = THUNK_JMP; opt_ibrs = 0; @@ -141,12 +148,14 @@ static int __init parse_spec_ctrl(const char *s) opt_msr_sc_pv = val; opt_rsb_pv = val; opt_md_clear_pv = val; + opt_ibpb_entry_pv = val; } else if ( (val = parse_boolean("hvm", s, ss)) >= 0 ) { opt_msr_sc_hvm = val; opt_rsb_hvm = val; opt_md_clear_hvm = val; + opt_ibpb_entry_hvm = val; } else if ( (val = parse_boolean("msr-sc", s, ss)) != -1 ) { @@ -211,6 +220,28 @@ static int __init parse_spec_ctrl(const char *s) break; } } + else if ( (val = parse_boolean("ibpb-entry", s, ss)) != -1 ) + { + switch ( val ) + { + case 0: + case 1: + opt_ibpb_entry_pv = opt_ibpb_entry_hvm = + opt_ibpb_entry_dom0 = val; + break; + + case -2: + s += strlen("ibpb-entry="); + if ( (val = parse_boolean("pv", s, ss)) >= 0 ) + opt_ibpb_entry_pv = val; + else if ( (val = parse_boolean("hvm", s, ss)) >= 0 ) + opt_ibpb_entry_hvm = val; + else + default: + rc = -EINVAL; + break; + } + } /* Xen's speculative sidechannel mitigation settings. */ else if ( !strncmp(s, "bti-thunk=", 10) ) @@ -474,27 +505,31 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps) * mitigation support for guests. */ #ifdef CONFIG_HVM - printk(" Support for HVM VMs:%s%s%s%s%s\n", + printk(" Support for HVM VMs:%s%s%s%s%s%s\n", (boot_cpu_has(X86_FEATURE_SC_MSR_HVM) || boot_cpu_has(X86_FEATURE_SC_RSB_HVM) || boot_cpu_has(X86_FEATURE_MD_CLEAR) || + boot_cpu_has(X86_FEATURE_IBPB_ENTRY_HVM) || opt_eager_fpu) ? "" : " None", boot_cpu_has(X86_FEATURE_SC_MSR_HVM) ? " MSR_SPEC_CTRL" : "", boot_cpu_has(X86_FEATURE_SC_RSB_HVM) ? " RSB" : "", opt_eager_fpu ? " EAGER_FPU" : "", - boot_cpu_has(X86_FEATURE_MD_CLEAR) ? " MD_CLEAR" : ""); + boot_cpu_has(X86_FEATURE_MD_CLEAR) ? " MD_CLEAR" : "", + boot_cpu_has(X86_FEATURE_IBPB_ENTRY_HVM) ? " IBPB-entry" : ""); #endif #ifdef CONFIG_PV - printk(" Support for PV VMs:%s%s%s%s%s\n", + printk(" Support for PV VMs:%s%s%s%s%s%s\n", (boot_cpu_has(X86_FEATURE_SC_MSR_PV) || boot_cpu_has(X86_FEATURE_SC_RSB_PV) || boot_cpu_has(X86_FEATURE_MD_CLEAR) || + boot_cpu_has(X86_FEATURE_IBPB_ENTRY_PV) || opt_eager_fpu) ? "" : " None", boot_cpu_has(X86_FEATURE_SC_MSR_PV) ? " MSR_SPEC_CTRL" : "", boot_cpu_has(X86_FEATURE_SC_RSB_PV) ? " RSB" : "", opt_eager_fpu ? " EAGER_FPU" : "", - boot_cpu_has(X86_FEATURE_MD_CLEAR) ? " MD_CLEAR" : ""); + boot_cpu_has(X86_FEATURE_MD_CLEAR) ? " MD_CLEAR" : "", + boot_cpu_has(X86_FEATURE_IBPB_ENTRY_PV) ? " IBPB-entry" : ""); printk(" XPTI (64-bit PV only): Dom0 %s, DomU %s (with%s PCID)\n", opt_xpti_hwdom ? "enabled" : "disabled", @@ -727,6 +762,55 @@ static bool __init should_use_eager_fpu(void) } } +static void __init ibpb_calculations(void) +{ + /* Check we have hardware IBPB support before using it... */ + if ( !boot_cpu_has(X86_FEATURE_IBRSB) && !boot_cpu_has(X86_FEATURE_IBPB) ) + { + opt_ibpb_entry_hvm = opt_ibpb_entry_pv = opt_ibpb_ctxt_switch = 0; + opt_ibpb_entry_dom0 = false; + return; + } + + /* + * IBPB-on-entry mitigations for Branch Type Confusion. + * + * IBPB && !BTC_NO selects all AMD/Hygon hardware, not known to be safe, + * that we can provide some form of mitigation on. + */ + if ( opt_ibpb_entry_pv == -1 ) + opt_ibpb_entry_pv = (IS_ENABLED(CONFIG_PV) && + boot_cpu_has(X86_FEATURE_IBPB) && + !boot_cpu_has(X86_FEATURE_BTC_NO)); + if ( opt_ibpb_entry_hvm == -1 ) + opt_ibpb_entry_hvm = (IS_ENABLED(CONFIG_HVM) && + boot_cpu_has(X86_FEATURE_IBPB) && + !boot_cpu_has(X86_FEATURE_BTC_NO)); + + if ( opt_ibpb_entry_pv ) + { + setup_force_cpu_cap(X86_FEATURE_IBPB_ENTRY_PV); + + /* + * We only need to flush in IST context if we're protecting against PV + * guests. HVM IBPB-on-entry protections are both atomic with + * NMI/#MC, so can't interrupt Xen ahead of having already flushed the + * BTB. + */ + default_spec_ctrl_flags |= SCF_ist_ibpb; + } + if ( opt_ibpb_entry_hvm ) + setup_force_cpu_cap(X86_FEATURE_IBPB_ENTRY_HVM); + + /* + * If we're using IBPB-on-entry to protect against PV and HVM guests + * (ignoring dom0 if trusted), then there's no need to also issue IBPB on + * context switch too. + */ + if ( opt_ibpb_ctxt_switch == -1 ) + opt_ibpb_ctxt_switch = !(opt_ibpb_entry_hvm && opt_ibpb_entry_pv); +} + /* Calculate whether this CPU is vulnerable to L1TF. */ static __init void l1tf_calculations(uint64_t caps) { @@ -982,8 +1066,12 @@ void spec_ctrl_init_domain(struct domain *d) bool verw = ((pv ? opt_md_clear_pv : opt_md_clear_hvm) || (opt_fb_clear_mmio && is_iommu_enabled(d))); + bool ibpb = ((pv ? opt_ibpb_entry_pv : opt_ibpb_entry_hvm) && + (d->domain_id != 0 || opt_ibpb_entry_dom0)); + d->arch.spec_ctrl_flags = (verw ? SCF_verw : 0) | + (ibpb ? SCF_entry_ibpb : 0) | 0; } @@ -1111,12 +1199,15 @@ void __init init_speculation_mitigations(void) } /* - * Use STIBP by default if the hardware hint is set. Otherwise, leave it - * off as it a severe performance pentalty on pre-eIBRS Intel hardware - * where it was retrofitted in microcode. + * Use STIBP by default on all AMD systems. Zen3 and later enumerate + * STIBP_ALWAYS, but STIBP is needed on Zen2 as part of the mitigations + * for Branch Type Confusion. + * + * Leave STIBP off by default on Intel. Pre-eIBRS systems suffer a + * substantial perf hit when it was implemented in microcode. */ if ( opt_stibp == -1 ) - opt_stibp = !!boot_cpu_has(X86_FEATURE_STIBP_ALWAYS); + opt_stibp = !!boot_cpu_has(X86_FEATURE_AMD_STIBP); if ( opt_stibp && (boot_cpu_has(X86_FEATURE_STIBP) || boot_cpu_has(X86_FEATURE_AMD_STIBP)) ) @@ -1169,9 +1260,7 @@ void __init init_speculation_mitigations(void) if ( opt_rsb_hvm ) setup_force_cpu_cap(X86_FEATURE_SC_RSB_HVM); - /* Check we have hardware IBPB support before using it... */ - if ( !boot_cpu_has(X86_FEATURE_IBRSB) && !boot_cpu_has(X86_FEATURE_IBPB) ) - opt_ibpb_ctxt_switch = false; + ibpb_calculations(); /* Check whether Eager FPU should be enabled by default. */ if ( opt_eager_fpu == -1 ) diff --git a/xen/include/asm-x86/spec_ctrl.h b/xen/include/asm-x86/spec_ctrl.h index 8b69a81917..2f15ae9814 100644 --- a/xen/include/asm-x86/spec_ctrl.h +++ b/xen/include/asm-x86/spec_ctrl.h @@ -65,7 +65,7 @@ void init_speculation_mitigations(void); void spec_ctrl_init_domain(struct domain *d); -extern bool opt_ibpb_ctxt_switch; +extern int8_t opt_ibpb_ctxt_switch; extern bool opt_ssbd; extern int8_t opt_eager_fpu; extern int8_t opt_l1d_flush; -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.13
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |