From ab3164079ee42ece7c49aecd70ee3d5e551f96f7 Mon Sep 17 00:00:00 2001 From: Michael Young Date: Jul 12 2022 20:34:09 +0000 Subject: Retbleed - arbitrary speculative code execution with return instructions [XSA-407, CVE-2022-23816, CVE-2022-23825, CVE-2022-29900] --- diff --git a/xen.git-09d533f4c80b7eaf9fb4e36ebba8259580857a9d.patch b/xen.git-09d533f4c80b7eaf9fb4e36ebba8259580857a9d.patch new file mode 100644 index 0000000..1285967 --- /dev/null +++ b/xen.git-09d533f4c80b7eaf9fb4e36ebba8259580857a9d.patch @@ -0,0 +1,93 @@ +From 09d533f4c80b7eaf9fb4e36ebba8259580857a9d Mon Sep 17 00:00:00 2001 +From: Andrew Cooper +Date: Tue, 12 Jul 2022 11:12:46 +0200 +Subject: [PATCH] x86/spec-ctrl: Only adjust MSR_SPEC_CTRL for idle with legacy + IBRS +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +Back at the time of the original Spectre-v2 fixes, it was recommended to clear +MSR_SPEC_CTRL when going idle. This is because of the side effects on the +sibling thread caused by the microcode IBRS and STIBP implementations which +were retrofitted to existing CPUs. + +However, there are no relevant cross-thread impacts for the hardware +IBRS/STIBP implementations, so this logic should not be used on Intel CPUs +supporting eIBRS, or any AMD CPUs; doing so only adds unnecessary latency to +the idle path. + +Furthermore, there's no point playing with MSR_SPEC_CTRL in the idle paths if +SMT is disabled for other reasons. + +Fixes: 8d03080d2a33 ("x86/spec-ctrl: Cease using thunk=lfence on AMD") +Signed-off-by: Andrew Cooper +Reviewed-by: Roger Pau Monné +master commit: ffc7694e0c99eea158c32aa164b7d1e1bb1dc46b +master date: 2022-06-30 18:07:13 +0100 +--- + xen/arch/x86/spec_ctrl.c | 10 ++++++++-- + xen/include/asm-x86/cpufeatures.h | 2 +- + xen/include/asm-x86/spec_ctrl.h | 5 +++-- + 3 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c +index 099113ba41..1ed5ceda8b 100644 +--- a/xen/arch/x86/spec_ctrl.c ++++ b/xen/arch/x86/spec_ctrl.c +@@ -1150,8 +1150,14 @@ void __init init_speculation_mitigations(void) + /* (Re)init BSP state now that default_spec_ctrl_flags has been calculated. */ + init_shadow_spec_ctrl_state(); + +- /* If Xen is using any MSR_SPEC_CTRL settings, adjust the idle path. */ +- if ( default_xen_spec_ctrl ) ++ /* ++ * For microcoded IBRS only (i.e. Intel, pre eIBRS), it is recommended to ++ * clear MSR_SPEC_CTRL before going idle, to avoid impacting sibling ++ * threads. Activate this if SMT is enabled, and Xen is using a non-zero ++ * MSR_SPEC_CTRL setting. ++ */ ++ if ( boot_cpu_has(X86_FEATURE_IBRSB) && !(caps & ARCH_CAPS_IBRS_ALL) && ++ hw_smt_enabled && default_xen_spec_ctrl ) + setup_force_cpu_cap(X86_FEATURE_SC_MSR_IDLE); + + xpti_init_default(caps); +diff --git a/xen/include/asm-x86/cpufeatures.h b/xen/include/asm-x86/cpufeatures.h +index bd45a144ee..493d338a08 100644 +--- a/xen/include/asm-x86/cpufeatures.h ++++ b/xen/include/asm-x86/cpufeatures.h +@@ -33,7 +33,7 @@ XEN_CPUFEATURE(SC_MSR_HVM, X86_SYNTH(17)) /* MSR_SPEC_CTRL used by Xen fo + XEN_CPUFEATURE(SC_RSB_PV, X86_SYNTH(18)) /* RSB overwrite needed for PV */ + XEN_CPUFEATURE(SC_RSB_HVM, X86_SYNTH(19)) /* RSB overwrite needed for HVM */ + XEN_CPUFEATURE(XEN_SELFSNOOP, X86_SYNTH(20)) /* SELFSNOOP gets used by Xen itself */ +-XEN_CPUFEATURE(SC_MSR_IDLE, X86_SYNTH(21)) /* (SC_MSR_PV || SC_MSR_HVM) && default_xen_spec_ctrl */ ++XEN_CPUFEATURE(SC_MSR_IDLE, X86_SYNTH(21)) /* Clear MSR_SPEC_CTRL on idle */ + XEN_CPUFEATURE(XEN_LBR, X86_SYNTH(22)) /* Xen uses MSR_DEBUGCTL.LBR */ + /* Bits 23,24 unused. */ + XEN_CPUFEATURE(SC_VERW_IDLE, X86_SYNTH(25)) /* VERW used by Xen for idle */ +diff --git a/xen/include/asm-x86/spec_ctrl.h b/xen/include/asm-x86/spec_ctrl.h +index 751355f471..7e83e0179f 100644 +--- a/xen/include/asm-x86/spec_ctrl.h ++++ b/xen/include/asm-x86/spec_ctrl.h +@@ -78,7 +78,8 @@ static always_inline void spec_ctrl_enter_idle(struct cpu_info *info) + uint32_t val = 0; + + /* +- * Branch Target Injection: ++ * It is recommended in some cases to clear MSR_SPEC_CTRL when going idle, ++ * to avoid impacting sibling threads. + * + * Latch the new shadow value, then enable shadowing, then update the MSR. + * There are no SMP issues here; only local processor ordering concerns. +@@ -114,7 +115,7 @@ static always_inline void spec_ctrl_exit_idle(struct cpu_info *info) + uint32_t val = info->xen_spec_ctrl; + + /* +- * Branch Target Injection: ++ * Restore MSR_SPEC_CTRL on exit from idle. + * + * Disable shadowing before updating the MSR. There are no SMP issues + * here; only local processor ordering concerns. +-- +2.30.2 + diff --git a/xen.git-db6ca8176ccc4ff7dfe3c06969af9ebfab0d7b04.patch b/xen.git-db6ca8176ccc4ff7dfe3c06969af9ebfab0d7b04.patch new file mode 100644 index 0000000..4d5bb71 --- /dev/null +++ b/xen.git-db6ca8176ccc4ff7dfe3c06969af9ebfab0d7b04.patch @@ -0,0 +1,233 @@ +From db6ca8176ccc4ff7dfe3c06969af9ebfab0d7b04 Mon Sep 17 00:00:00 2001 +From: Andrew Cooper +Date: Tue, 12 Jul 2022 11:13:33 +0200 +Subject: [PATCH] x86/spec-ctrl: Knobs for STIBP and PSFD, and follow hardware + STIBP hint +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +STIBP and PSFD are slightly weird bits, because they're both implied by other +bits in MSR_SPEC_CTRL. Add fine grain controls for them, and take the +implications into account when setting IBRS/SSBD. + +Rearrange the IBPB text/variables/logic to keep all the MSR_SPEC_CTRL bits +together, for consistency. + +However, AMD have a hardware hint CPUID bit recommending that STIBP be set +unilaterally. This is advertised on Zen3, so follow the recommendation. +Furthermore, in such cases, set STIBP behind the guest's back for now. This +has negligible overhead for the guest, but saves a WRMSR on vmentry. This is +the only default change. + +Signed-off-by: Andrew Cooper +Reviewed-by: Jan Beulich +Reviewed-by: Roger Pau Monné +master commit: fef244b179c06fcdfa581f7d57fa6e578c49ff50 +master date: 2022-06-30 18:07:13 +0100 +--- + docs/misc/xen-command-line.pandoc | 21 +++++++--- + xen/arch/x86/hvm/svm/vmcb.c | 9 +++++ + xen/arch/x86/spec_ctrl.c | 65 ++++++++++++++++++++++++++----- + 3 files changed, 81 insertions(+), 14 deletions(-) + +diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc +index a642e43476..46e9c58d35 100644 +--- a/docs/misc/xen-command-line.pandoc ++++ b/docs/misc/xen-command-line.pandoc +@@ -2234,8 +2234,9 @@ By default SSBD will be mitigated at runtime (i.e `ssbd=runtime`). + + ### spec-ctrl (x86) + > `= List of [ , xen=, {pv,hvm,msr-sc,rsb,md-clear}=, +-> bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,eager-fpu, +-> l1d-flush,branch-harden,srb-lock,unpriv-mmio}= ]` ++> bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,psfd, ++> eager-fpu,l1d-flush,branch-harden,srb-lock, ++> unpriv-mmio}= ]` + + Controls for speculative execution sidechannel mitigations. By default, Xen + will pick the most appropriate mitigations based on compiled in support, +@@ -2285,9 +2286,10 @@ On hardware supporting IBRS (Indirect Branch Restricted Speculation), the + If Xen is not using IBRS itself, functionality is still set up so IBRS can be + virtualised for guests. + +-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. ++On hardware supporting STIBP (Single Thread Indirect Branch Predictors), the ++`stibp=` option can be used to force or prevent Xen using the feature itself. ++By default, Xen will use STIBP when IBRS is in use (IBRS implies STIBP), and ++when hardware hints recommend using it as a blanket setting. + + On hardware supporting SSBD (Speculative Store Bypass Disable), the `ssbd=` + option can be used to force or prevent Xen using the feature itself. On AMD +@@ -2295,6 +2297,15 @@ hardware, this is a global option applied at boot, and not virtualised for + guest use. On Intel hardware, the feature is virtualised for guests, + independently of Xen's choice of setting. + ++On hardware supporting PSFD (Predictive Store Forwarding Disable), the `psfd=` ++option can be used to force or prevent Xen using the feature itself. By ++default, Xen will not use PSFD. PSFD is implied by SSBD, and SSBD is off by ++default. ++ ++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. ++ + On all hardware, the `eager-fpu=` option can be used to force or prevent Xen + from using fully eager FPU context switches. This is currently implemented as + a global control. By default, Xen will choose to use fully eager context +diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c +index 565e997155..ef7224eb5d 100644 +--- a/xen/arch/x86/hvm/svm/vmcb.c ++++ b/xen/arch/x86/hvm/svm/vmcb.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + struct vmcb_struct *alloc_vmcb(void) + { +@@ -176,6 +177,14 @@ static int construct_vmcb(struct vcpu *v) + vmcb->_pause_filter_thresh = SVM_PAUSETHRESH_INIT; + } + ++ /* ++ * When default_xen_spec_ctrl simply SPEC_CTRL_STIBP, default this behind ++ * the back of the VM too. Our SMT topology isn't accurate, the overhead ++ * is neglegable, and doing this saves a WRMSR on the vmentry path. ++ */ ++ if ( default_xen_spec_ctrl == SPEC_CTRL_STIBP ) ++ v->arch.msrs->spec_ctrl.raw = SPEC_CTRL_STIBP; ++ + return 0; + } + +diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c +index 1ed5ceda8b..dfdd45c358 100644 +--- a/xen/arch/x86/spec_ctrl.c ++++ b/xen/arch/x86/spec_ctrl.c +@@ -48,9 +48,13 @@ static enum ind_thunk { + THUNK_LFENCE, + THUNK_JMP, + } opt_thunk __initdata = THUNK_DEFAULT; ++ + static int8_t __initdata opt_ibrs = -1; ++int8_t __initdata opt_stibp = -1; ++bool __read_mostly opt_ssbd; ++int8_t __initdata opt_psfd = -1; ++ + bool __read_mostly opt_ibpb = true; +-bool __read_mostly opt_ssbd = false; + int8_t __read_mostly opt_eager_fpu = -1; + int8_t __read_mostly opt_l1d_flush = -1; + static bool __initdata opt_branch_harden = true; +@@ -172,12 +176,20 @@ static int __init parse_spec_ctrl(const char *s) + else + rc = -EINVAL; + } ++ ++ /* Bits in MSR_SPEC_CTRL. */ + else if ( (val = parse_boolean("ibrs", s, ss)) >= 0 ) + opt_ibrs = val; +- else if ( (val = parse_boolean("ibpb", s, ss)) >= 0 ) +- opt_ibpb = val; ++ else if ( (val = parse_boolean("stibp", s, ss)) >= 0 ) ++ opt_stibp = val; + else if ( (val = parse_boolean("ssbd", s, ss)) >= 0 ) + opt_ssbd = val; ++ else if ( (val = parse_boolean("psfd", s, ss)) >= 0 ) ++ opt_psfd = val; ++ ++ /* Misc settings. */ ++ else if ( (val = parse_boolean("ibpb", s, ss)) >= 0 ) ++ opt_ibpb = val; + else if ( (val = parse_boolean("eager-fpu", s, ss)) >= 0 ) + opt_eager_fpu = val; + else if ( (val = parse_boolean("l1d-flush", s, ss)) >= 0 ) +@@ -376,7 +388,7 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps) + "\n"); + + /* Settings for Xen's protection, irrespective of guests. */ +- printk(" Xen settings: BTI-Thunk %s, SPEC_CTRL: %s%s%s%s, Other:%s%s%s%s%s\n", ++ printk(" Xen settings: BTI-Thunk %s, SPEC_CTRL: %s%s%s%s%s, Other:%s%s%s%s%s\n", + thunk == THUNK_NONE ? "N/A" : + thunk == THUNK_RETPOLINE ? "RETPOLINE" : + thunk == THUNK_LFENCE ? "LFENCE" : +@@ -390,6 +402,9 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps) + (!boot_cpu_has(X86_FEATURE_SSBD) && + !boot_cpu_has(X86_FEATURE_AMD_SSBD)) ? "" : + (default_xen_spec_ctrl & SPEC_CTRL_SSBD) ? " SSBD+" : " SSBD-", ++ (!boot_cpu_has(X86_FEATURE_PSFD) && ++ !boot_cpu_has(X86_FEATURE_INTEL_PSFD)) ? "" : ++ (default_xen_spec_ctrl & SPEC_CTRL_PSFD) ? " PSFD+" : " PSFD-", + !(caps & ARCH_CAPS_TSX_CTRL) ? "" : + (opt_tsx & 1) ? " TSX+" : " TSX-", + !cpu_has_srbds_ctrl ? "" : +@@ -979,10 +994,7 @@ void __init init_speculation_mitigations(void) + if ( !has_spec_ctrl ) + printk(XENLOG_WARNING "?!? CET active, but no MSR_SPEC_CTRL?\n"); + else if ( opt_ibrs == -1 ) +- { + opt_ibrs = ibrs = true; +- default_xen_spec_ctrl |= SPEC_CTRL_IBRS | SPEC_CTRL_STIBP; +- } + + if ( opt_thunk == THUNK_DEFAULT || opt_thunk == THUNK_RETPOLINE ) + thunk = THUNK_JMP; +@@ -1086,14 +1098,49 @@ void __init init_speculation_mitigations(void) + setup_force_cpu_cap(X86_FEATURE_SC_MSR_HVM); + } + +- /* If we have IBRS available, see whether we should use it. */ ++ /* Figure out default_xen_spec_ctrl. */ + if ( has_spec_ctrl && ibrs ) ++ { ++ /* IBRS implies STIBP. */ ++ if ( opt_stibp == -1 ) ++ opt_stibp = 1; ++ + default_xen_spec_ctrl |= SPEC_CTRL_IBRS; ++ } ++ ++ /* ++ * 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. ++ */ ++ if ( opt_stibp == -1 ) ++ opt_stibp = !!boot_cpu_has(X86_FEATURE_STIBP_ALWAYS); ++ ++ if ( opt_stibp && (boot_cpu_has(X86_FEATURE_STIBP) || ++ boot_cpu_has(X86_FEATURE_AMD_STIBP)) ) ++ default_xen_spec_ctrl |= SPEC_CTRL_STIBP; + +- /* If we have SSBD available, see whether we should use it. */ + if ( opt_ssbd && (boot_cpu_has(X86_FEATURE_SSBD) || + boot_cpu_has(X86_FEATURE_AMD_SSBD)) ) ++ { ++ /* SSBD implies PSFD */ ++ if ( opt_psfd == -1 ) ++ opt_psfd = 1; ++ + default_xen_spec_ctrl |= SPEC_CTRL_SSBD; ++ } ++ ++ /* ++ * Don't use PSFD by default. AMD designed the predictor to ++ * auto-clear on privilege change. PSFD is implied by SSBD, which is ++ * off by default. ++ */ ++ if ( opt_psfd == -1 ) ++ opt_psfd = 0; ++ ++ if ( opt_psfd && (boot_cpu_has(X86_FEATURE_PSFD) || ++ boot_cpu_has(X86_FEATURE_INTEL_PSFD)) ) ++ default_xen_spec_ctrl |= SPEC_CTRL_PSFD; + + /* + * PV guests can create RSB entries for any linear address they control, +-- +2.30.2 + diff --git a/xen.git-eec5b02403a9df2523527caad24f17af5060fbe7.patch b/xen.git-eec5b02403a9df2523527caad24f17af5060fbe7.patch new file mode 100644 index 0000000..1394851 --- /dev/null +++ b/xen.git-eec5b02403a9df2523527caad24f17af5060fbe7.patch @@ -0,0 +1,86 @@ +From eec5b02403a9df2523527caad24f17af5060fbe7 Mon Sep 17 00:00:00 2001 +From: Andrew Cooper +Date: Tue, 12 Jul 2022 11:15:03 +0200 +Subject: [PATCH] xen/cmdline: Extend parse_boolean() to signal a name match + +This will help parsing a sub-option which has boolean and non-boolean options +available. + +First, rework 'int val' into 'bool has_neg_prefix'. This inverts it's value, +but the resulting logic is far easier to follow. + +Second, reject anything of the form 'no-$FOO=' which excludes ambiguous +constructs such as 'no-$foo=yes' which have never been valid. + +This just leaves the case where everything is otherwise fine, but parse_bool() +can't interpret the provided string. + +Signed-off-by: Andrew Cooper +Reviewed-by: Juergen Gross +Reviewed-by: Jan Beulich +master commit: 382326cac528dd1eb0d04efd5c05363c453e29f4 +master date: 2022-07-11 15:21:35 +0100 +--- + xen/common/kernel.c | 20 ++++++++++++++++---- + xen/include/xen/lib.h | 3 ++- + 2 files changed, 18 insertions(+), 5 deletions(-) + +diff --git a/xen/common/kernel.c b/xen/common/kernel.c +index e119e5401f..7ed96521f9 100644 +--- a/xen/common/kernel.c ++++ b/xen/common/kernel.c +@@ -272,9 +272,9 @@ int parse_bool(const char *s, const char *e) + int parse_boolean(const char *name, const char *s, const char *e) + { + size_t slen, nlen; +- int val = !!strncmp(s, "no-", 3); ++ bool has_neg_prefix = !strncmp(s, "no-", 3); + +- if ( !val ) ++ if ( has_neg_prefix ) + s += 3; + + slen = e ? ({ ASSERT(e >= s); e - s; }) : strlen(s); +@@ -286,11 +286,23 @@ int parse_boolean(const char *name, const char *s, const char *e) + + /* Exact, unadorned name? Result depends on the 'no-' prefix. */ + if ( slen == nlen ) +- return val; ++ return !has_neg_prefix; ++ ++ /* Inexact match with a 'no-' prefix? Not valid. */ ++ if ( has_neg_prefix ) ++ return -1; + + /* =$SOMETHING? Defer to the regular boolean parsing. */ + if ( s[nlen] == '=' ) +- return parse_bool(&s[nlen + 1], e); ++ { ++ int b = parse_bool(&s[nlen + 1], e); ++ ++ if ( b >= 0 ) ++ return b; ++ ++ /* Not a boolean, but the name matched. Signal specially. */ ++ return -2; ++ } + + /* Unrecognised. Give up. */ + return -1; +diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h +index c6987973bf..2296044caf 100644 +--- a/xen/include/xen/lib.h ++++ b/xen/include/xen/lib.h +@@ -80,7 +80,8 @@ int parse_bool(const char *s, const char *e); + /** + * Given a specific name, parses a string of the form: + * [no-]$NAME[=...] +- * returning 0 or 1 for a recognised boolean, or -1 for an error. ++ * returning 0 or 1 for a recognised boolean. Returns -1 for general errors, ++ * and -2 for "not a boolean, but $NAME= matches". + */ + int parse_boolean(const char *name, const char *s, const char *e); + +-- +2.30.2 + diff --git a/xen.git-f066c8bb3e5686141cef6fa1dc86ea9f37c5388a.patch b/xen.git-f066c8bb3e5686141cef6fa1dc86ea9f37c5388a.patch new file mode 100644 index 0000000..56cdada --- /dev/null +++ b/xen.git-f066c8bb3e5686141cef6fa1dc86ea9f37c5388a.patch @@ -0,0 +1,137 @@ +From f066c8bb3e5686141cef6fa1dc86ea9f37c5388a Mon Sep 17 00:00:00 2001 +From: Andrew Cooper +Date: Tue, 12 Jul 2022 11:15:37 +0200 +Subject: [PATCH] x86/spec-ctrl: Add fine-grained cmdline suboptions for + primitives + +Support controling the PV/HVM suboption of msr-sc/rsb/md-clear, which +previously wasn't possible. + +Signed-off-by: Andrew Cooper +Reviewed-by: Jan Beulich +master commit: 27357c394ba6e1571a89105b840ce1c6f026485c +master date: 2022-07-11 15:21:35 +0100 +--- + docs/misc/xen-command-line.pandoc | 12 ++++-- + xen/arch/x86/spec_ctrl.c | 66 ++++++++++++++++++++++++++----- + 2 files changed, 66 insertions(+), 12 deletions(-) + +diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc +index 46e9c58d35..1bbdb55129 100644 +--- a/docs/misc/xen-command-line.pandoc ++++ b/docs/misc/xen-command-line.pandoc +@@ -2233,7 +2233,8 @@ not be able to control the state of the mitigation. + By default SSBD will be mitigated at runtime (i.e `ssbd=runtime`). + + ### spec-ctrl (x86) +-> `= List of [ , xen=, {pv,hvm,msr-sc,rsb,md-clear}=, ++> `= List of [ , xen=, {pv,hvm}=, ++> {msr-sc,rsb,md-clear}=|{pv,hvm}=, + > bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,psfd, + > eager-fpu,l1d-flush,branch-harden,srb-lock, + > unpriv-mmio}= ]` +@@ -2258,12 +2259,17 @@ in place for guests to use. + + Use of a positive boolean value for either of these options is invalid. + +-The booleans `pv=`, `hvm=`, `msr-sc=`, `rsb=` and `md-clear=` offer fine ++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 Xen's ability to virtualise support for guests to use. ++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. ++* Each other option can be used either as a plain boolean ++ (e.g. `spec-ctrl=rsb` to control both the PV and HVM sub-options), or with ++ `pv=` or `hvm=` subsuboptions (e.g. `spec-ctrl=rsb=no-hvm` to disable HVM ++ RSB only). ++ + * `msr-sc=` offers control over Xen's support for manipulating `MSR_SPEC_CTRL` + on entry and exit. These blocks are necessary to virtualise support for + guests and if disabled, guests will be unable to use IBRS/STIBP/SSBD/etc. +diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c +index ae74943c10..9507e5da60 100644 +--- a/xen/arch/x86/spec_ctrl.c ++++ b/xen/arch/x86/spec_ctrl.c +@@ -147,20 +147,68 @@ static int __init parse_spec_ctrl(const char *s) + opt_rsb_hvm = val; + opt_md_clear_hvm = val; + } +- else if ( (val = parse_boolean("msr-sc", s, ss)) >= 0 ) ++ else if ( (val = parse_boolean("msr-sc", s, ss)) != -1 ) + { +- opt_msr_sc_pv = val; +- opt_msr_sc_hvm = val; ++ switch ( val ) ++ { ++ case 0: ++ case 1: ++ opt_msr_sc_pv = opt_msr_sc_hvm = val; ++ break; ++ ++ case -2: ++ s += strlen("msr-sc="); ++ if ( (val = parse_boolean("pv", s, ss)) >= 0 ) ++ opt_msr_sc_pv = val; ++ else if ( (val = parse_boolean("hvm", s, ss)) >= 0 ) ++ opt_msr_sc_hvm = val; ++ else ++ default: ++ rc = -EINVAL; ++ break; ++ } + } +- else if ( (val = parse_boolean("rsb", s, ss)) >= 0 ) ++ else if ( (val = parse_boolean("rsb", s, ss)) != -1 ) + { +- opt_rsb_pv = val; +- opt_rsb_hvm = val; ++ switch ( val ) ++ { ++ case 0: ++ case 1: ++ opt_rsb_pv = opt_rsb_hvm = val; ++ break; ++ ++ case -2: ++ s += strlen("rsb="); ++ if ( (val = parse_boolean("pv", s, ss)) >= 0 ) ++ opt_rsb_pv = val; ++ else if ( (val = parse_boolean("hvm", s, ss)) >= 0 ) ++ opt_rsb_hvm = val; ++ else ++ default: ++ rc = -EINVAL; ++ break; ++ } + } +- else if ( (val = parse_boolean("md-clear", s, ss)) >= 0 ) ++ else if ( (val = parse_boolean("md-clear", s, ss)) != -1 ) + { +- opt_md_clear_pv = val; +- opt_md_clear_hvm = val; ++ switch ( val ) ++ { ++ case 0: ++ case 1: ++ opt_md_clear_pv = opt_md_clear_hvm = val; ++ break; ++ ++ case -2: ++ s += strlen("md-clear="); ++ if ( (val = parse_boolean("pv", s, ss)) >= 0 ) ++ opt_md_clear_pv = val; ++ else if ( (val = parse_boolean("hvm", s, ss)) >= 0 ) ++ opt_md_clear_hvm = val; ++ else ++ default: ++ rc = -EINVAL; ++ break; ++ } + } + + /* Xen's speculative sidechannel mitigation settings. */ +-- +2.30.2 + diff --git a/xen.spec b/xen.spec index c849eb2..02e1c71 100644 --- a/xen.spec +++ b/xen.spec @@ -55,7 +55,7 @@ Summary: Xen is a virtual machine monitor Name: xen Version: 4.16.1 -Release: 5%{?dist} +Release: 6%{?dist} License: GPLv2+ and LGPLv2+ and BSD URL: http://xen.org/ Source0: https://downloads.xenproject.org/release/xen/%{version}/xen-%{version}.tar.gz @@ -123,6 +123,18 @@ Patch55: xsa404-4.16-1.patch Patch56: xsa404-4.16-2.patch Patch57: xsa404-4.16-3.patch Patch58: xsa403-4.16-1.patch +Patch59: xen.git-09d533f4c80b7eaf9fb4e36ebba8259580857a9d.patch +Patch60: xen.git-db6ca8176ccc4ff7dfe3c06969af9ebfab0d7b04.patch +Patch61: xen.git-eec5b02403a9df2523527caad24f17af5060fbe7.patch +Patch62: xen.git-f066c8bb3e5686141cef6fa1dc86ea9f37c5388a.patch +Patch63: xsa407-4.16-1.patch +Patch64: xsa407-4.16-2.patch +Patch65: xsa407-4.16-3.patch +Patch66: xsa407-4.16-4.patch +Patch67: xsa407-4.16-5.patch +Patch68: xsa407-4.16-6.patch +Patch69: xsa407-4.16-7.patch +Patch70: xsa407-4.16-8.patch %if %build_qemutrad @@ -347,6 +359,18 @@ manage Xen virtual machines. %patch56 -p1 %patch57 -p1 %patch58 -p1 +%patch59 -p1 +%patch60 -p1 +%patch61 -p1 +%patch62 -p1 +%patch63 -p1 +%patch64 -p1 +%patch65 -p1 +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 +%patch70 -p1 # qemu-xen-traditional patches pushd tools/qemu-xen-traditional @@ -962,6 +986,10 @@ fi %endif %changelog +* Tue Jul 12 2022 Michael Young - 4.16.1-6 +- Retbleed - arbitrary speculative code execution with return instructions + [XSA-407, CVE-2022-23816, CVE-2022-23825, CVE-2022-29900] + * Tue Jul 05 2022 Michael Young - 4.16.1-5 - Linux disk/nic frontends data leaks [XSA-403, CVE-2022-26365, CVE-2022-33740, CVE-2022-33741, CVE-2022-33742] (#2104747) diff --git a/xsa407-4.16-1.patch b/xsa407-4.16-1.patch new file mode 100644 index 0000000..d6dc7fc --- /dev/null +++ b/xsa407-4.16-1.patch @@ -0,0 +1,153 @@ +From: Andrew Cooper +Subject: x86/spec-ctrl: Rework spec_ctrl_flags context switching + +We are shortly going to need to context switch new bits in both the vcpu and +S3 paths. Introduce SCF_IST_MASK and SCF_DOM_MASK, and rework d->arch.verw +into d->arch.spec_ctrl_flags to accommodate. + +No functional change. + +This is part of XSA-407. + +Signed-off-by: Andrew Cooper +Reviewed-by: Jan Beulich + +diff --git a/xen/arch/x86/acpi/power.c b/xen/arch/x86/acpi/power.c +index 5eaa77f66a28..dd397f713067 100644 +--- a/xen/arch/x86/acpi/power.c ++++ b/xen/arch/x86/acpi/power.c +@@ -248,8 +248,8 @@ static int enter_state(u32 state) + error = 0; + + ci = get_cpu_info(); +- /* Avoid NMI/#MC using MSR_SPEC_CTRL until we've reloaded microcode. */ +- ci->spec_ctrl_flags &= ~SCF_ist_wrmsr; ++ /* Avoid NMI/#MC using unsafe MSRs until we've reloaded microcode. */ ++ ci->spec_ctrl_flags &= ~SCF_IST_MASK; + + ACPI_FLUSH_CPU_CACHE(); + +@@ -292,8 +292,8 @@ static int enter_state(u32 state) + if ( !recheck_cpu_features(0) ) + panic("Missing previously available feature(s)\n"); + +- /* Re-enabled default NMI/#MC use of MSR_SPEC_CTRL. */ +- ci->spec_ctrl_flags |= (default_spec_ctrl_flags & SCF_ist_wrmsr); ++ /* Re-enabled default NMI/#MC use of MSRs now microcode is loaded. */ ++ ci->spec_ctrl_flags |= (default_spec_ctrl_flags & SCF_IST_MASK); + + if ( boot_cpu_has(X86_FEATURE_IBRSB) || boot_cpu_has(X86_FEATURE_IBRS) ) + { +diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c +index 1fe6644a71ae..82a0b73cf6ef 100644 +--- a/xen/arch/x86/domain.c ++++ b/xen/arch/x86/domain.c +@@ -2092,10 +2092,10 @@ void context_switch(struct vcpu *prev, struct vcpu *next) + } + } + +- /* Update the top-of-stack block with the VERW disposition. */ +- info->spec_ctrl_flags &= ~SCF_verw; +- if ( nextd->arch.verw ) +- info->spec_ctrl_flags |= SCF_verw; ++ /* Update the top-of-stack block with the new spec_ctrl settings. */ ++ info->spec_ctrl_flags = ++ (info->spec_ctrl_flags & ~SCF_DOM_MASK) | ++ (nextd->arch.spec_ctrl_flags & SCF_DOM_MASK); + } + + sched_context_switched(prev, next); +diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c +index 9507e5da60a9..7e646680f1c7 100644 +--- a/xen/arch/x86/spec_ctrl.c ++++ b/xen/arch/x86/spec_ctrl.c +@@ -1010,9 +1010,12 @@ void spec_ctrl_init_domain(struct domain *d) + { + bool pv = is_pv_domain(d); + +- d->arch.verw = +- (pv ? opt_md_clear_pv : opt_md_clear_hvm) || +- (opt_fb_clear_mmio && is_iommu_enabled(d)); ++ bool verw = ((pv ? opt_md_clear_pv : opt_md_clear_hvm) || ++ (opt_fb_clear_mmio && is_iommu_enabled(d))); ++ ++ d->arch.spec_ctrl_flags = ++ (verw ? SCF_verw : 0) | ++ 0; + } + + void __init init_speculation_mitigations(void) +diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h +index 2398a1d99da9..e4c099262cb7 100644 +--- a/xen/include/asm-x86/domain.h ++++ b/xen/include/asm-x86/domain.h +@@ -319,8 +319,7 @@ struct arch_domain + uint32_t pci_cf8; + uint8_t cmos_idx; + +- /* Use VERW on return-to-guest for its flushing side effect. */ +- bool verw; ++ uint8_t spec_ctrl_flags; /* See SCF_DOM_MASK */ + + union { + struct pv_domain pv; +diff --git a/xen/include/asm-x86/spec_ctrl.h b/xen/include/asm-x86/spec_ctrl.h +index 7e83e0179fb9..3cd72e40305f 100644 +--- a/xen/include/asm-x86/spec_ctrl.h ++++ b/xen/include/asm-x86/spec_ctrl.h +@@ -20,12 +20,40 @@ + #ifndef __X86_SPEC_CTRL_H__ + #define __X86_SPEC_CTRL_H__ + +-/* Encoding of cpuinfo.spec_ctrl_flags */ ++/* ++ * Encoding of: ++ * cpuinfo.spec_ctrl_flags ++ * default_spec_ctrl_flags ++ * domain.spec_ctrl_flags ++ * ++ * Live settings are in the top-of-stack block, because they need to be ++ * accessable when XPTI is active. Some settings are fixed from boot, some ++ * context switched per domain, and some inhibited in the S3 path. ++ */ + #define SCF_use_shadow (1 << 0) + #define SCF_ist_wrmsr (1 << 1) + #define SCF_ist_rsb (1 << 2) + #define SCF_verw (1 << 3) + ++/* ++ * The IST paths (NMI/#MC) can interrupt any arbitrary context. Some ++ * functionality requires updated microcode to work. ++ * ++ * On boot, this is easy; we load microcode before figuring out which ++ * speculative protections to apply. However, on the S3 resume path, we must ++ * be able to disable the configured mitigations until microcode is reloaded. ++ * ++ * These are the controls to inhibit on the S3 resume path until microcode has ++ * been reloaded. ++ */ ++#define SCF_IST_MASK (SCF_ist_wrmsr) ++ ++/* ++ * Some speculative protections are per-domain. These settings are merged ++ * into the top-of-stack block in the context switch path. ++ */ ++#define SCF_DOM_MASK (SCF_verw) ++ + #ifndef __ASSEMBLY__ + + #include +diff --git a/xen/include/asm-x86/spec_ctrl_asm.h b/xen/include/asm-x86/spec_ctrl_asm.h +index 5a590bac44aa..66b00d511fc6 100644 +--- a/xen/include/asm-x86/spec_ctrl_asm.h ++++ b/xen/include/asm-x86/spec_ctrl_asm.h +@@ -248,9 +248,6 @@ + + /* + * Use in IST interrupt/exception context. May interrupt Xen or PV context. +- * Fine grain control of SCF_ist_wrmsr is needed for safety in the S3 resume +- * path to avoid using MSR_SPEC_CTRL before the microcode introducing it has +- * been reloaded. + */ + .macro SPEC_CTRL_ENTRY_FROM_INTR_IST + /* diff --git a/xsa407-4.16-2.patch b/xsa407-4.16-2.patch new file mode 100644 index 0000000..012d028 --- /dev/null +++ b/xsa407-4.16-2.patch @@ -0,0 +1,99 @@ +From: Andrew Cooper +Subject: x86/spec-ctrl: Rename SCF_ist_wrmsr to SCF_ist_sc_msr + +We are about to introduce SCF_ist_ibpb, at which point SCF_ist_wrmsr becomes +ambiguous. + +No functional change. + +This is part of XSA-407. + +Signed-off-by: Andrew Cooper +Reviewed-by: Jan Beulich + +diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c +index 7e646680f1c7..89f95c083e1b 100644 +--- a/xen/arch/x86/spec_ctrl.c ++++ b/xen/arch/x86/spec_ctrl.c +@@ -1115,7 +1115,7 @@ void __init init_speculation_mitigations(void) + { + if ( opt_msr_sc_pv ) + { +- default_spec_ctrl_flags |= SCF_ist_wrmsr; ++ default_spec_ctrl_flags |= SCF_ist_sc_msr; + setup_force_cpu_cap(X86_FEATURE_SC_MSR_PV); + } + +@@ -1126,7 +1126,7 @@ void __init init_speculation_mitigations(void) + * Xen's value is not restored atomically. An early NMI hitting + * the VMExit path needs to restore Xen's value for safety. + */ +- default_spec_ctrl_flags |= SCF_ist_wrmsr; ++ default_spec_ctrl_flags |= SCF_ist_sc_msr; + setup_force_cpu_cap(X86_FEATURE_SC_MSR_HVM); + } + } +@@ -1139,7 +1139,7 @@ void __init init_speculation_mitigations(void) + * on real hardware matches the availability of MSR_SPEC_CTRL in the + * first place. + * +- * No need for SCF_ist_wrmsr because Xen's value is restored ++ * No need for SCF_ist_sc_msr because Xen's value is restored + * atomically WRT NMIs in the VMExit path. + * + * TODO: Adjust cpu_has_svm_spec_ctrl to be usable earlier on boot. +diff --git a/xen/include/asm-x86/spec_ctrl.h b/xen/include/asm-x86/spec_ctrl.h +index 3cd72e40305f..f8f0ac47e759 100644 +--- a/xen/include/asm-x86/spec_ctrl.h ++++ b/xen/include/asm-x86/spec_ctrl.h +@@ -31,7 +31,7 @@ + * context switched per domain, and some inhibited in the S3 path. + */ + #define SCF_use_shadow (1 << 0) +-#define SCF_ist_wrmsr (1 << 1) ++#define SCF_ist_sc_msr (1 << 1) + #define SCF_ist_rsb (1 << 2) + #define SCF_verw (1 << 3) + +@@ -46,7 +46,7 @@ + * These are the controls to inhibit on the S3 resume path until microcode has + * been reloaded. + */ +-#define SCF_IST_MASK (SCF_ist_wrmsr) ++#define SCF_IST_MASK (SCF_ist_sc_msr) + + /* + * Some speculative protections are per-domain. These settings are merged +diff --git a/xen/include/asm-x86/spec_ctrl_asm.h b/xen/include/asm-x86/spec_ctrl_asm.h +index 66b00d511fc6..0ff1b118f882 100644 +--- a/xen/include/asm-x86/spec_ctrl_asm.h ++++ b/xen/include/asm-x86/spec_ctrl_asm.h +@@ -266,8 +266,8 @@ + + .L\@_skip_rsb: + +- test $SCF_ist_wrmsr, %al +- jz .L\@_skip_wrmsr ++ test $SCF_ist_sc_msr, %al ++ jz .L\@_skip_msr_spec_ctrl + + xor %edx, %edx + testb $3, UREGS_cs(%rsp) +@@ -290,7 +290,7 @@ UNLIKELY_DISPATCH_LABEL(\@_serialise): + * to speculate around the WRMSR. As a result, we need a dispatch + * serialising instruction in the else clause. + */ +-.L\@_skip_wrmsr: ++.L\@_skip_msr_spec_ctrl: + lfence + UNLIKELY_END(\@_serialise) + .endm +@@ -301,7 +301,7 @@ UNLIKELY_DISPATCH_LABEL(\@_serialise): + * Requires %rbx=stack_end + * Clobbers %rax, %rcx, %rdx + */ +- testb $SCF_ist_wrmsr, STACK_CPUINFO_FIELD(spec_ctrl_flags)(%rbx) ++ testb $SCF_ist_sc_msr, STACK_CPUINFO_FIELD(spec_ctrl_flags)(%rbx) + jz .L\@_skip + + DO_SPEC_CTRL_EXIT_TO_XEN diff --git a/xsa407-4.16-3.patch b/xsa407-4.16-3.patch new file mode 100644 index 0000000..c6f7e6b --- /dev/null +++ b/xsa407-4.16-3.patch @@ -0,0 +1,86 @@ +From: Andrew Cooper +Subject: x86/spec-ctrl: Rename opt_ibpb to opt_ibpb_ctxt_switch + +We are about to introduce the use of IBPB at different points in Xen, making +opt_ibpb ambiguous. Rename it to opt_ibpb_ctxt_switch. + +No functional change. + +Signed-off-by: Andrew Cooper +Reviewed-by: Jan Beulich + +diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c +index 82a0b73cf6ef..0d39981550ca 100644 +--- a/xen/arch/x86/domain.c ++++ b/xen/arch/x86/domain.c +@@ -2064,7 +2064,7 @@ void context_switch(struct vcpu *prev, struct vcpu *next) + + ctxt_switch_levelling(next); + +- if ( opt_ibpb && !is_idle_domain(nextd) ) ++ if ( opt_ibpb_ctxt_switch && !is_idle_domain(nextd) ) + { + static DEFINE_PER_CPU(unsigned int, last); + unsigned int *last_id = &this_cpu(last); +diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c +index 89f95c083e1b..f4ae36eae2d0 100644 +--- a/xen/arch/x86/spec_ctrl.c ++++ b/xen/arch/x86/spec_ctrl.c +@@ -54,7 +54,7 @@ int8_t __initdata opt_stibp = -1; + bool __read_mostly opt_ssbd; + int8_t __initdata opt_psfd = -1; + +-bool __read_mostly opt_ibpb = true; ++bool __read_mostly opt_ibpb_ctxt_switch = true; + int8_t __read_mostly opt_eager_fpu = -1; + int8_t __read_mostly opt_l1d_flush = -1; + static bool __initdata opt_branch_harden = true; +@@ -117,7 +117,7 @@ static int __init parse_spec_ctrl(const char *s) + + opt_thunk = THUNK_JMP; + opt_ibrs = 0; +- opt_ibpb = false; ++ opt_ibpb_ctxt_switch = false; + opt_ssbd = false; + opt_l1d_flush = 0; + opt_branch_harden = false; +@@ -238,7 +238,7 @@ static int __init parse_spec_ctrl(const char *s) + + /* Misc settings. */ + else if ( (val = parse_boolean("ibpb", s, ss)) >= 0 ) +- opt_ibpb = val; ++ opt_ibpb_ctxt_switch = val; + else if ( (val = parse_boolean("eager-fpu", s, ss)) >= 0 ) + opt_eager_fpu = val; + else if ( (val = parse_boolean("l1d-flush", s, ss)) >= 0 ) +@@ -458,7 +458,7 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps) + (opt_tsx & 1) ? " TSX+" : " TSX-", + !cpu_has_srbds_ctrl ? "" : + opt_srb_lock ? " SRB_LOCK+" : " SRB_LOCK-", +- opt_ibpb ? " IBPB" : "", ++ opt_ibpb_ctxt_switch ? " IBPB-ctxt" : "", + opt_l1d_flush ? " L1D_FLUSH" : "", + opt_md_clear_pv || opt_md_clear_hvm || + opt_fb_clear_mmio ? " VERW" : "", +@@ -1240,7 +1240,7 @@ void __init init_speculation_mitigations(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 = false; ++ opt_ibpb_ctxt_switch = false; + + /* 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 f8f0ac47e759..fb4365575620 100644 +--- a/xen/include/asm-x86/spec_ctrl.h ++++ b/xen/include/asm-x86/spec_ctrl.h +@@ -63,7 +63,7 @@ + void init_speculation_mitigations(void); + void spec_ctrl_init_domain(struct domain *d); + +-extern bool opt_ibpb; ++extern bool opt_ibpb_ctxt_switch; + extern bool opt_ssbd; + extern int8_t opt_eager_fpu; + extern int8_t opt_l1d_flush; diff --git a/xsa407-4.16-4.patch b/xsa407-4.16-4.patch new file mode 100644 index 0000000..50e5f0f --- /dev/null +++ b/xsa407-4.16-4.patch @@ -0,0 +1,96 @@ +From: Andrew Cooper +Subject: x86/spec-ctrl: Rework SPEC_CTRL_ENTRY_FROM_INTR_IST + +We are shortly going to add a conditional IBPB in this path. + +Therefore, we cannot hold spec_ctrl_flags in %eax, and rely on only clobbering +it after we're done with its contents. %rbx is available for use, and the +more normal register to hold preserved information in. + +With %rax freed up, use it instead of %rdx for the RSB tmp register, and for +the adjustment to spec_ctrl_flags. + +This leaves no use of %rdx, except as 0 for the upper half of WRMSR. In +practice, %rdx is 0 from SAVE_ALL on all paths and isn't likely to change in +the foreseeable future, so update the macro entry requirements to state this +dependency. This marginal optimisation can be revisited if circumstances +change. + +No practical change. + +This is part of XSA-407. + +Signed-off-by: Andrew Cooper +Reviewed-by: Jan Beulich + +diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S +index 2a86938f1f32..a1810bf4d311 100644 +--- a/xen/arch/x86/x86_64/entry.S ++++ b/xen/arch/x86/x86_64/entry.S +@@ -932,7 +932,7 @@ ENTRY(double_fault) + + GET_STACK_END(14) + +- SPEC_CTRL_ENTRY_FROM_INTR_IST /* Req: %rsp=regs, %r14=end, Clob: acd */ ++ SPEC_CTRL_ENTRY_FROM_INTR_IST /* Req: %rsp=regs, %r14=end, %rdx=0, Clob: abcd */ + /* WARNING! `ret`, `call *`, `jmp *` not safe before this point. */ + + mov STACK_CPUINFO_FIELD(xen_cr3)(%r14), %rbx +@@ -968,7 +968,7 @@ handle_ist_exception: + + GET_STACK_END(14) + +- SPEC_CTRL_ENTRY_FROM_INTR_IST /* Req: %rsp=regs, %r14=end, Clob: acd */ ++ SPEC_CTRL_ENTRY_FROM_INTR_IST /* Req: %rsp=regs, %r14=end, %rdx=0, Clob: abcd */ + /* WARNING! `ret`, `call *`, `jmp *` not safe before this point. */ + + mov STACK_CPUINFO_FIELD(xen_cr3)(%r14), %rcx +diff --git a/xen/include/asm-x86/spec_ctrl_asm.h b/xen/include/asm-x86/spec_ctrl_asm.h +index 0ff1b118f882..15e24cde00d1 100644 +--- a/xen/include/asm-x86/spec_ctrl_asm.h ++++ b/xen/include/asm-x86/spec_ctrl_asm.h +@@ -251,34 +251,33 @@ + */ + .macro SPEC_CTRL_ENTRY_FROM_INTR_IST + /* +- * Requires %rsp=regs, %r14=stack_end +- * Clobbers %rax, %rcx, %rdx ++ * Requires %rsp=regs, %r14=stack_end, %rdx=0 ++ * Clobbers %rax, %rbx, %rcx, %rdx + * + * This is logical merge of DO_OVERWRITE_RSB and DO_SPEC_CTRL_ENTRY + * maybexen=1, but with conditionals rather than alternatives. + */ +- movzbl STACK_CPUINFO_FIELD(spec_ctrl_flags)(%r14), %eax ++ movzbl STACK_CPUINFO_FIELD(spec_ctrl_flags)(%r14), %ebx + +- test $SCF_ist_rsb, %al ++ test $SCF_ist_rsb, %bl + jz .L\@_skip_rsb + +- DO_OVERWRITE_RSB tmp=rdx /* Clobbers %rcx/%rdx */ ++ DO_OVERWRITE_RSB /* Clobbers %rax/%rcx */ + + .L\@_skip_rsb: + +- test $SCF_ist_sc_msr, %al ++ test $SCF_ist_sc_msr, %bl + jz .L\@_skip_msr_spec_ctrl + +- xor %edx, %edx ++ xor %eax, %eax + testb $3, UREGS_cs(%rsp) +- setnz %dl +- not %edx +- and %dl, STACK_CPUINFO_FIELD(spec_ctrl_flags)(%r14) ++ setnz %al ++ not %eax ++ and %al, STACK_CPUINFO_FIELD(spec_ctrl_flags)(%r14) + + /* Load Xen's intended value. */ + mov $MSR_SPEC_CTRL, %ecx + movzbl STACK_CPUINFO_FIELD(xen_spec_ctrl)(%r14), %eax +- xor %edx, %edx + wrmsr + + /* Opencoded UNLIKELY_START() with no condition. */ diff --git a/xsa407-4.16-5.patch b/xsa407-4.16-5.patch new file mode 100644 index 0000000..ef6da7c --- /dev/null +++ b/xsa407-4.16-5.patch @@ -0,0 +1,285 @@ +From: Andrew Cooper +Subject: x86/spec-ctrl: Support IBPB-on-entry + +We are going to need this to mitigate Branch Type Confusion on AMD/Hygon CPUs, +but as we've talked about using it in other cases too, arrange to support it +generally. However, this is also very expensive in some cases, so we're going +to want per-domain controls. + +Introduce SCF_ist_ibpb and SCF_entry_ibpb controls, adding them to the IST and +DOM masks as appropriate. Also introduce X86_FEATURE_IBPB_ENTRY_{PV,HVM} to +to patch the code blocks. + +For SVM, the STGI is serialising enough to protect against Spectre-v1 attacks, +so no "else lfence" is necessary. VT-x will use use the MSR host load list, +so doesn't need any code in the VMExit path. + +For the IST path, we can't safely check CPL==0 to skip a flush, as we might +have hit an entry path before it's IBPB. As IST hitting Xen is rare, flush +irrespective of CPL. A later path, SCF_ist_sc_msr, provides Spectre-v1 +safety. + +For the PV paths, we know we're interrupting CPL>0, while for the INTR paths, +we can safely check CPL==0. Only flush when interrupting guest context. + +An "else lfence" is needed for safety, but we want to be able to skip it on +unaffected CPUs, so the block wants to be an alternative, which means the +lfence has to be inline rather than UNLIKELY() (the replacement block doesn't +have displacements fixed up for anything other than the first instruction). + +As with SPEC_CTRL_ENTRY_FROM_INTR_IST, %rdx is 0 on entry so rely on this to +shrink the logic marginally. Update the comments to specify this new +dependency. + +This is part of XSA-407. + +Signed-off-by: Andrew Cooper +Reviewed-by: Jan Beulich + +diff --git a/xen/arch/x86/hvm/svm/entry.S b/xen/arch/x86/hvm/svm/entry.S +index 4ae55a2ef605..0ff4008060fa 100644 +--- a/xen/arch/x86/hvm/svm/entry.S ++++ b/xen/arch/x86/hvm/svm/entry.S +@@ -97,7 +97,19 @@ __UNLIKELY_END(nsvm_hap) + + GET_CURRENT(bx) + +- /* SPEC_CTRL_ENTRY_FROM_SVM Req: %rsp=regs/cpuinfo Clob: acd */ ++ /* SPEC_CTRL_ENTRY_FROM_SVM Req: %rsp=regs/cpuinfo, %rdx=0 Clob: acd */ ++ ++ .macro svm_vmexit_cond_ibpb ++ testb $SCF_entry_ibpb, CPUINFO_xen_spec_ctrl(%rsp) ++ jz .L_skip_ibpb ++ ++ mov $MSR_PRED_CMD, %ecx ++ mov $PRED_CMD_IBPB, %eax ++ wrmsr ++.L_skip_ibpb: ++ .endm ++ ALTERNATIVE "", svm_vmexit_cond_ibpb, X86_FEATURE_IBPB_ENTRY_HVM ++ + ALTERNATIVE "", DO_OVERWRITE_RSB, X86_FEATURE_SC_RSB_HVM + + .macro svm_vmexit_spec_ctrl +@@ -114,6 +126,10 @@ __UNLIKELY_END(nsvm_hap) + ALTERNATIVE "", svm_vmexit_spec_ctrl, X86_FEATURE_SC_MSR_HVM + /* WARNING! `ret`, `call *`, `jmp *` not safe before this point. */ + ++ /* ++ * STGI is executed unconditionally, and is sufficiently serialising ++ * to safely resolve any Spectre-v1 concerns in the above logic. ++ */ + stgi + GLOBAL(svm_stgi_label) + mov %rsp,%rdi +diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c +index f9f9bc18cdbc..dd817cee4e69 100644 +--- a/xen/arch/x86/hvm/vmx/vmcs.c ++++ b/xen/arch/x86/hvm/vmx/vmcs.c +@@ -1345,6 +1345,10 @@ static int construct_vmcs(struct vcpu *v) + rc = vmx_add_msr(v, MSR_FLUSH_CMD, FLUSH_CMD_L1D, + VMX_MSR_GUEST_LOADONLY); + ++ if ( !rc && (d->arch.spec_ctrl_flags & SCF_entry_ibpb) ) ++ rc = vmx_add_msr(v, MSR_PRED_CMD, PRED_CMD_IBPB, ++ VMX_MSR_HOST); ++ + out: + vmx_vmcs_exit(v); + +diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S +index 5fd6dbbd4513..b86d38d1c50d 100644 +--- a/xen/arch/x86/x86_64/compat/entry.S ++++ b/xen/arch/x86/x86_64/compat/entry.S +@@ -18,7 +18,7 @@ ENTRY(entry_int82) + movl $HYPERCALL_VECTOR, 4(%rsp) + SAVE_ALL compat=1 /* DPL1 gate, restricted to 32bit PV guests only. */ + +- SPEC_CTRL_ENTRY_FROM_PV /* Req: %rsp=regs/cpuinfo, Clob: acd */ ++ SPEC_CTRL_ENTRY_FROM_PV /* Req: %rsp=regs/cpuinfo, %rdx=0, Clob: acd */ + /* WARNING! `ret`, `call *`, `jmp *` not safe before this point. */ + + CR4_PV32_RESTORE +diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S +index a1810bf4d311..fba8ae498f74 100644 +--- a/xen/arch/x86/x86_64/entry.S ++++ b/xen/arch/x86/x86_64/entry.S +@@ -260,7 +260,7 @@ ENTRY(lstar_enter) + movl $TRAP_syscall, 4(%rsp) + SAVE_ALL + +- SPEC_CTRL_ENTRY_FROM_PV /* Req: %rsp=regs/cpuinfo, Clob: acd */ ++ SPEC_CTRL_ENTRY_FROM_PV /* Req: %rsp=regs/cpuinfo, %rdx=0, Clob: acd */ + /* WARNING! `ret`, `call *`, `jmp *` not safe before this point. */ + + GET_STACK_END(bx) +@@ -298,7 +298,7 @@ ENTRY(cstar_enter) + movl $TRAP_syscall, 4(%rsp) + SAVE_ALL + +- SPEC_CTRL_ENTRY_FROM_PV /* Req: %rsp=regs/cpuinfo, Clob: acd */ ++ SPEC_CTRL_ENTRY_FROM_PV /* Req: %rsp=regs/cpuinfo, %rdx=0, Clob: acd */ + /* WARNING! `ret`, `call *`, `jmp *` not safe before this point. */ + + GET_STACK_END(bx) +@@ -338,7 +338,7 @@ GLOBAL(sysenter_eflags_saved) + movl $TRAP_syscall, 4(%rsp) + SAVE_ALL + +- SPEC_CTRL_ENTRY_FROM_PV /* Req: %rsp=regs/cpuinfo, Clob: acd */ ++ SPEC_CTRL_ENTRY_FROM_PV /* Req: %rsp=regs/cpuinfo, %rdx=0, Clob: acd */ + /* WARNING! `ret`, `call *`, `jmp *` not safe before this point. */ + + GET_STACK_END(bx) +@@ -392,7 +392,7 @@ ENTRY(int80_direct_trap) + movl $0x80, 4(%rsp) + SAVE_ALL + +- SPEC_CTRL_ENTRY_FROM_PV /* Req: %rsp=regs/cpuinfo, Clob: acd */ ++ SPEC_CTRL_ENTRY_FROM_PV /* Req: %rsp=regs/cpuinfo, %rdx=0, Clob: acd */ + /* WARNING! `ret`, `call *`, `jmp *` not safe before this point. */ + + GET_STACK_END(bx) +@@ -674,7 +674,7 @@ ENTRY(common_interrupt) + + GET_STACK_END(14) + +- SPEC_CTRL_ENTRY_FROM_INTR /* Req: %rsp=regs, %r14=end, Clob: acd */ ++ SPEC_CTRL_ENTRY_FROM_INTR /* Req: %rsp=regs, %r14=end, %rdx=0, Clob: acd */ + /* WARNING! `ret`, `call *`, `jmp *` not safe before this point. */ + + mov STACK_CPUINFO_FIELD(xen_cr3)(%r14), %rcx +@@ -708,7 +708,7 @@ GLOBAL(handle_exception) + + GET_STACK_END(14) + +- SPEC_CTRL_ENTRY_FROM_INTR /* Req: %rsp=regs, %r14=end, Clob: acd */ ++ SPEC_CTRL_ENTRY_FROM_INTR /* Req: %rsp=regs, %r14=end, %rdx=0, Clob: acd */ + /* WARNING! `ret`, `call *`, `jmp *` not safe before this point. */ + + mov STACK_CPUINFO_FIELD(xen_cr3)(%r14), %rcx +diff --git a/xen/include/asm-x86/cpufeatures.h b/xen/include/asm-x86/cpufeatures.h +index 493d338a085e..672c9ee22ba2 100644 +--- a/xen/include/asm-x86/cpufeatures.h ++++ b/xen/include/asm-x86/cpufeatures.h +@@ -39,6 +39,8 @@ XEN_CPUFEATURE(XEN_LBR, X86_SYNTH(22)) /* Xen uses MSR_DEBUGCTL.LBR */ + XEN_CPUFEATURE(SC_VERW_IDLE, X86_SYNTH(25)) /* VERW used by Xen for idle */ + XEN_CPUFEATURE(XEN_SHSTK, X86_SYNTH(26)) /* Xen uses CET Shadow Stacks */ + XEN_CPUFEATURE(XEN_IBT, X86_SYNTH(27)) /* Xen uses CET Indirect Branch Tracking */ ++XEN_CPUFEATURE(IBPB_ENTRY_PV, X86_SYNTH(28)) /* MSR_PRED_CMD used by Xen for PV */ ++XEN_CPUFEATURE(IBPB_ENTRY_HVM, X86_SYNTH(29)) /* MSR_PRED_CMD used by Xen for HVM */ + + /* Bug words follow the synthetic words. */ + #define X86_NR_BUG 1 +diff --git a/xen/include/asm-x86/spec_ctrl.h b/xen/include/asm-x86/spec_ctrl.h +index fb4365575620..3fc599a817c4 100644 +--- a/xen/include/asm-x86/spec_ctrl.h ++++ b/xen/include/asm-x86/spec_ctrl.h +@@ -34,6 +34,8 @@ + #define SCF_ist_sc_msr (1 << 1) + #define SCF_ist_rsb (1 << 2) + #define SCF_verw (1 << 3) ++#define SCF_ist_ibpb (1 << 4) ++#define SCF_entry_ibpb (1 << 5) + + /* + * The IST paths (NMI/#MC) can interrupt any arbitrary context. Some +@@ -46,13 +48,13 @@ + * These are the controls to inhibit on the S3 resume path until microcode has + * been reloaded. + */ +-#define SCF_IST_MASK (SCF_ist_sc_msr) ++#define SCF_IST_MASK (SCF_ist_sc_msr | SCF_ist_ibpb) + + /* + * Some speculative protections are per-domain. These settings are merged + * into the top-of-stack block in the context switch path. + */ +-#define SCF_DOM_MASK (SCF_verw) ++#define SCF_DOM_MASK (SCF_verw | SCF_entry_ibpb) + + #ifndef __ASSEMBLY__ + +diff --git a/xen/include/asm-x86/spec_ctrl_asm.h b/xen/include/asm-x86/spec_ctrl_asm.h +index 15e24cde00d1..9eb4ad9ab71d 100644 +--- a/xen/include/asm-x86/spec_ctrl_asm.h ++++ b/xen/include/asm-x86/spec_ctrl_asm.h +@@ -88,6 +88,35 @@ + * - SPEC_CTRL_EXIT_TO_{SVM,VMX} + */ + ++.macro DO_SPEC_CTRL_COND_IBPB maybexen:req ++/* ++ * Requires %rsp=regs (also cpuinfo if !maybexen) ++ * Requires %r14=stack_end (if maybexen), %rdx=0 ++ * Clobbers %rax, %rcx, %rdx ++ * ++ * Conditionally issue IBPB if SCF_entry_ibpb is active. In the maybexen ++ * case, we can safely look at UREGS_cs to skip taking the hit when ++ * interrupting Xen. ++ */ ++ .if \maybexen ++ testb $SCF_entry_ibpb, STACK_CPUINFO_FIELD(spec_ctrl_flags)(%r14) ++ jz .L\@_skip ++ testb $3, UREGS_cs(%rsp) ++ .else ++ testb $SCF_entry_ibpb, CPUINFO_xen_spec_ctrl(%rsp) ++ .endif ++ jz .L\@_skip ++ ++ mov $MSR_PRED_CMD, %ecx ++ mov $PRED_CMD_IBPB, %eax ++ wrmsr ++ jmp .L\@_done ++ ++.L\@_skip: ++ lfence ++.L\@_done: ++.endm ++ + .macro DO_OVERWRITE_RSB tmp=rax + /* + * Requires nothing +@@ -225,12 +254,16 @@ + + /* Use after an entry from PV context (syscall/sysenter/int80/int82/etc). */ + #define SPEC_CTRL_ENTRY_FROM_PV \ ++ ALTERNATIVE "", __stringify(DO_SPEC_CTRL_COND_IBPB maybexen=0), \ ++ X86_FEATURE_IBPB_ENTRY_PV; \ + ALTERNATIVE "", DO_OVERWRITE_RSB, X86_FEATURE_SC_RSB_PV; \ + ALTERNATIVE "", __stringify(DO_SPEC_CTRL_ENTRY maybexen=0), \ + X86_FEATURE_SC_MSR_PV + + /* Use in interrupt/exception context. May interrupt Xen or PV context. */ + #define SPEC_CTRL_ENTRY_FROM_INTR \ ++ ALTERNATIVE "", __stringify(DO_SPEC_CTRL_COND_IBPB maybexen=1), \ ++ X86_FEATURE_IBPB_ENTRY_PV; \ + ALTERNATIVE "", DO_OVERWRITE_RSB, X86_FEATURE_SC_RSB_PV; \ + ALTERNATIVE "", __stringify(DO_SPEC_CTRL_ENTRY maybexen=1), \ + X86_FEATURE_SC_MSR_PV +@@ -254,11 +287,23 @@ + * Requires %rsp=regs, %r14=stack_end, %rdx=0 + * Clobbers %rax, %rbx, %rcx, %rdx + * +- * This is logical merge of DO_OVERWRITE_RSB and DO_SPEC_CTRL_ENTRY +- * maybexen=1, but with conditionals rather than alternatives. ++ * This is logical merge of: ++ * DO_SPEC_CTRL_COND_IBPB maybexen=0 ++ * DO_OVERWRITE_RSB ++ * DO_SPEC_CTRL_ENTRY maybexen=1 ++ * but with conditionals rather than alternatives. + */ + movzbl STACK_CPUINFO_FIELD(spec_ctrl_flags)(%r14), %ebx + ++ test $SCF_ist_ibpb, %bl ++ jz .L\@_skip_ibpb ++ ++ mov $MSR_PRED_CMD, %ecx ++ mov $PRED_CMD_IBPB, %eax ++ wrmsr ++ ++.L\@_skip_ibpb: ++ + test $SCF_ist_rsb, %bl + jz .L\@_skip_rsb + diff --git a/xsa407-4.16-6.patch b/xsa407-4.16-6.patch new file mode 100644 index 0000000..92290dc --- /dev/null +++ b/xsa407-4.16-6.patch @@ -0,0 +1,93 @@ +From: Andrew Cooper +Subject: x86/cpuid: Enumeration for BTC_NO + +BTC_NO indicates that hardware is not succeptable to Branch Type Confusion. + +Zen3 CPUs don't suffer BTC. + +This is part of XSA-407. + +Signed-off-by: Andrew Cooper +Reviewed-by: Jan Beulich + +diff --git a/tools/libs/light/libxl_cpuid.c b/tools/libs/light/libxl_cpuid.c +index d462f9e421ed..bf6fdee360a9 100644 +--- a/tools/libs/light/libxl_cpuid.c ++++ b/tools/libs/light/libxl_cpuid.c +@@ -288,6 +288,7 @@ int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str) + {"virt-ssbd", 0x80000008, NA, CPUID_REG_EBX, 25, 1}, + {"ssb-no", 0x80000008, NA, CPUID_REG_EBX, 26, 1}, + {"psfd", 0x80000008, NA, CPUID_REG_EBX, 28, 1}, ++ {"btc-no", 0x80000008, NA, CPUID_REG_EBX, 29, 1}, + + {"nc", 0x80000008, NA, CPUID_REG_ECX, 0, 8}, + {"apicidsize", 0x80000008, NA, CPUID_REG_ECX, 12, 4}, +diff --git a/tools/misc/xen-cpuid.c b/tools/misc/xen-cpuid.c +index bc7dcf55757a..fe22f5f5b68b 100644 +--- a/tools/misc/xen-cpuid.c ++++ b/tools/misc/xen-cpuid.c +@@ -158,7 +158,7 @@ static const char *const str_e8b[32] = + /* [22] */ [23] = "ppin", + [24] = "amd-ssbd", [25] = "virt-ssbd", + [26] = "ssb-no", +- [28] = "psfd", ++ [28] = "psfd", [29] = "btc-no", + }; + + static const char *const str_7d0[32] = +diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c +index b3b9a0df5fed..b158e3acb5c7 100644 +--- a/xen/arch/x86/cpu/amd.c ++++ b/xen/arch/x86/cpu/amd.c +@@ -847,6 +847,16 @@ static void init_amd(struct cpuinfo_x86 *c) + warning_add(text); + } + break; ++ ++ case 0x19: ++ /* ++ * Zen3 (Fam19h model < 0x10) parts are not susceptible to ++ * Branch Type Confusion, but predate the allocation of the ++ * BTC_NO bit. Fill it back in if we're not virtualised. ++ */ ++ if (!cpu_has_hypervisor && !cpu_has(c, X86_FEATURE_BTC_NO)) ++ __set_bit(X86_FEATURE_BTC_NO, c->x86_capability); ++ break; + } + + display_cacheinfo(c); +diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c +index f4ae36eae2d0..0f101c057f3e 100644 +--- a/xen/arch/x86/spec_ctrl.c ++++ b/xen/arch/x86/spec_ctrl.c +@@ -388,7 +388,7 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps) + * Hardware read-only information, stating immunity to certain issues, or + * suggestions of which mitigation to use. + */ +- printk(" Hardware hints:%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", ++ printk(" Hardware hints:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + (caps & ARCH_CAPS_RDCL_NO) ? " RDCL_NO" : "", + (caps & ARCH_CAPS_IBRS_ALL) ? " IBRS_ALL" : "", + (caps & ARCH_CAPS_RSBA) ? " RSBA" : "", +@@ -403,7 +403,8 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps) + (e8b & cpufeat_mask(X86_FEATURE_IBRS_ALWAYS)) ? " IBRS_ALWAYS" : "", + (e8b & cpufeat_mask(X86_FEATURE_STIBP_ALWAYS)) ? " STIBP_ALWAYS" : "", + (e8b & cpufeat_mask(X86_FEATURE_IBRS_FAST)) ? " IBRS_FAST" : "", +- (e8b & cpufeat_mask(X86_FEATURE_IBRS_SAME_MODE)) ? " IBRS_SAME_MODE" : ""); ++ (e8b & cpufeat_mask(X86_FEATURE_IBRS_SAME_MODE)) ? " IBRS_SAME_MODE" : "", ++ (e8b & cpufeat_mask(X86_FEATURE_BTC_NO)) ? " BTC_NO" : ""); + + /* Hardware features which need driving to mitigate issues. */ + printk(" Hardware features:%s%s%s%s%s%s%s%s%s%s%s%s\n", +diff --git a/xen/include/public/arch-x86/cpufeatureset.h b/xen/include/public/arch-x86/cpufeatureset.h +index 743b857dcd5c..e7b8167800a2 100644 +--- a/xen/include/public/arch-x86/cpufeatureset.h ++++ b/xen/include/public/arch-x86/cpufeatureset.h +@@ -266,6 +266,7 @@ XEN_CPUFEATURE(AMD_SSBD, 8*32+24) /*S MSR_SPEC_CTRL.SSBD available */ + XEN_CPUFEATURE(VIRT_SSBD, 8*32+25) /* MSR_VIRT_SPEC_CTRL.SSBD */ + XEN_CPUFEATURE(SSB_NO, 8*32+26) /*A Hardware not vulnerable to SSB */ + XEN_CPUFEATURE(PSFD, 8*32+28) /*S MSR_SPEC_CTRL.PSFD */ ++XEN_CPUFEATURE(BTC_NO, 8*32+29) /*A Hardware not vulnerable to Branch Type Confusion */ + + /* Intel-defined CPU features, CPUID level 0x00000007:0.edx, word 9 */ + XEN_CPUFEATURE(AVX512_4VNNIW, 9*32+ 2) /*A AVX512 Neural Network Instructions */ diff --git a/xsa407-4.16-7.patch b/xsa407-4.16-7.patch new file mode 100644 index 0000000..b71a0f8 --- /dev/null +++ b/xsa407-4.16-7.patch @@ -0,0 +1,94 @@ +From: Andrew Cooper +Subject: x86/spec-ctrl: Enable Zen2 chickenbit + +... as instructed in the Branch Type Confusion whitepaper. + +This is part of XSA-407. + +Signed-off-by: Andrew Cooper + +diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c +index b158e3acb5c7..37ac84ddd74d 100644 +--- a/xen/arch/x86/cpu/amd.c ++++ b/xen/arch/x86/cpu/amd.c +@@ -731,6 +731,31 @@ void amd_init_ssbd(const struct cpuinfo_x86 *c) + printk_once(XENLOG_ERR "No SSBD controls available\n"); + } + ++/* ++ * On Zen2 we offer this chicken (bit) on the altar of Speculation. ++ * ++ * Refer to the AMD Branch Type Confusion whitepaper: ++ * https://XXX ++ * ++ * Setting this unnamed bit supposedly causes prediction information on ++ * non-branch instructions to be ignored. It is to be set unilaterally in ++ * newer microcode. ++ * ++ * This chickenbit is something unrelated on Zen1, and Zen1 vs Zen2 isn't a ++ * simple model number comparison, so use STIBP as a heuristic to separate the ++ * two uarches in Fam17h(AMD)/18h(Hygon). ++ */ ++void amd_init_spectral_chicken(void) ++{ ++ uint64_t val, chickenbit = 1 << 1; ++ ++ if (cpu_has_hypervisor || !boot_cpu_has(X86_FEATURE_AMD_STIBP)) ++ return; ++ ++ if (rdmsr_safe(MSR_AMD64_DE_CFG2, val) == 0 && !(val & chickenbit)) ++ wrmsr_safe(MSR_AMD64_DE_CFG2, val | chickenbit); ++} ++ + void __init detect_zen2_null_seg_behaviour(void) + { + uint64_t base; +@@ -796,6 +821,9 @@ static void init_amd(struct cpuinfo_x86 *c) + + amd_init_ssbd(c); + ++ if (c->x86 == 0x17) ++ amd_init_spectral_chicken(); ++ + /* Probe for NSCB on Zen2 CPUs when not virtualised */ + if (!cpu_has_hypervisor && !cpu_has_nscb && c == &boot_cpu_data && + c->x86 == 0x17) +diff --git a/xen/arch/x86/cpu/cpu.h b/xen/arch/x86/cpu/cpu.h +index b593bd85f04f..145bc5156a86 100644 +--- a/xen/arch/x86/cpu/cpu.h ++++ b/xen/arch/x86/cpu/cpu.h +@@ -22,4 +22,5 @@ void early_init_amd(struct cpuinfo_x86 *c); + void amd_log_freq(const struct cpuinfo_x86 *c); + void amd_init_lfence(struct cpuinfo_x86 *c); + void amd_init_ssbd(const struct cpuinfo_x86 *c); ++void amd_init_spectral_chicken(void); + void detect_zen2_null_seg_behaviour(void); +diff --git a/xen/arch/x86/cpu/hygon.c b/xen/arch/x86/cpu/hygon.c +index cdc94130dd2e..6f8d491297e8 100644 +--- a/xen/arch/x86/cpu/hygon.c ++++ b/xen/arch/x86/cpu/hygon.c +@@ -41,6 +41,12 @@ static void init_hygon(struct cpuinfo_x86 *c) + detect_zen2_null_seg_behaviour(); + + /* ++ * TODO: Check heuristic safety with Hygon first ++ if (c->x86 == 0x18) ++ amd_init_spectral_chicken(); ++ */ ++ ++ /* + * Hygon CPUs before Zen2 don't clear segment bases/limits when + * loading a NULL selector. + */ +diff --git a/xen/include/asm-x86/msr-index.h b/xen/include/asm-x86/msr-index.h +index 72bc32ba04ff..d3735e499e0f 100644 +--- a/xen/include/asm-x86/msr-index.h ++++ b/xen/include/asm-x86/msr-index.h +@@ -361,6 +361,7 @@ + #define MSR_AMD64_DE_CFG 0xc0011029 + #define AMD64_DE_CFG_LFENCE_SERIALISE (_AC(1, ULL) << 1) + #define MSR_AMD64_EX_CFG 0xc001102c ++#define MSR_AMD64_DE_CFG2 0xc00110e3 + + #define MSR_AMD64_DR0_ADDRESS_MASK 0xc0011027 + #define MSR_AMD64_DR1_ADDRESS_MASK 0xc0011019 diff --git a/xsa407-4.16-8.patch b/xsa407-4.16-8.patch new file mode 100644 index 0000000..8d53169 --- /dev/null +++ b/xsa407-4.16-8.patch @@ -0,0 +1,293 @@ +From: Andrew Cooper +Subject: 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 +Reviewed-by: Jan Beulich + +diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc +index 1bbdb55129cc..bd6826d0ae05 100644 +--- a/docs/misc/xen-command-line.pandoc ++++ b/docs/misc/xen-command-line.pandoc +@@ -2234,7 +2234,7 @@ By default SSBD will be mitigated at runtime (i.e `ssbd=runtime`). + + ### spec-ctrl (x86) + > `= List of [ , xen=, {pv,hvm}=, +-> {msr-sc,rsb,md-clear}=|{pv,hvm}=, ++> {msr-sc,rsb,md-clear,ibpb-entry}=|{pv,hvm}=, + > bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,psfd, + > eager-fpu,l1d-flush,branch-harden,srb-lock, + > unpriv-mmio}= ]` +@@ -2259,9 +2259,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. +@@ -2280,6 +2281,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 0f101c057f3e..1d9796c34d71 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; + static bool __initdata opt_branch_harden = true; +@@ -114,6 +118,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; +@@ -140,12 +147,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 ) + { +@@ -210,6 +219,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) ) +@@ -477,27 +508,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", +@@ -759,6 +794,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) + { +@@ -1014,8 +1098,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; + } + +@@ -1162,12 +1250,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)) ) +@@ -1239,9 +1330,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 3fc599a817c4..9403b81dc7af 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;