summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '0049-x86-shskt-Disable-CET-SS-on-parts-susceptible-to-fra.patch')
-rw-r--r--0049-x86-shskt-Disable-CET-SS-on-parts-susceptible-to-fra.patch195
1 files changed, 195 insertions, 0 deletions
diff --git a/0049-x86-shskt-Disable-CET-SS-on-parts-susceptible-to-fra.patch b/0049-x86-shskt-Disable-CET-SS-on-parts-susceptible-to-fra.patch
new file mode 100644
index 0000000..a34217e
--- /dev/null
+++ b/0049-x86-shskt-Disable-CET-SS-on-parts-susceptible-to-fra.patch
@@ -0,0 +1,195 @@
+From 8202b9cf84674c5b23a89c4b8722afbb9787f917 Mon Sep 17 00:00:00 2001
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Date: Fri, 3 Mar 2023 07:56:16 +0100
+Subject: [PATCH 49/89] x86/shskt: Disable CET-SS on parts susceptible to
+ fractured updates
+
+Refer to Intel SDM Rev 70 (Dec 2022), Vol3 17.2.3 "Supervisor Shadow Stack
+Token".
+
+Architecturally, an event delivery which starts in CPL<3 and switches shadow
+stack will first validate the Supervisor Shadow Stack Token (setting the busy
+bit), then pushes CS/LIP/SSP. One example of this is an NMI interrupting Xen.
+
+Some CPUs suffer from an issue called fracturing, whereby a fault/vmexit/etc
+between setting the busy bit and completing the event injection renders the
+action non-restartable, because when it comes time to restart, the busy bit is
+found to be already set.
+
+This is far more easily encountered under virt, yet it is not the fault of the
+hypervisor, nor the fault of the guest kernel. The fault lies somewhere
+between the architectural specification, and the uarch behaviour.
+
+Intel have allocated CPUID.7[1].ecx[18] CET_SSS to enumerate that supervisor
+shadow stacks are safe to use. Because of how Xen lays out its shadow stacks,
+fracturing is not expected to be a problem on native.
+
+Detect this case on boot and default to not using shstk if virtualised.
+Specifying `cet=shstk` on the command line will override this heuristic and
+enable shadow stacks irrespective.
+
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+master commit: 01e7477d1b081cff4288ff9f51ec59ee94c03ee0
+master date: 2023-02-09 18:26:17 +0000
+---
+ docs/misc/xen-command-line.pandoc | 7 +++-
+ tools/libs/light/libxl_cpuid.c | 2 +
+ tools/misc/xen-cpuid.c | 1 +
+ xen/arch/x86/cpu/common.c | 11 ++++-
+ xen/arch/x86/setup.c | 46 +++++++++++++++++----
+ xen/include/public/arch-x86/cpufeatureset.h | 1 +
+ 6 files changed, 57 insertions(+), 11 deletions(-)
+
+diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
+index e7fe8b0cc9..807ca51fb2 100644
+--- a/docs/misc/xen-command-line.pandoc
++++ b/docs/misc/xen-command-line.pandoc
+@@ -287,10 +287,15 @@ can be maintained with the pv-shim mechanism.
+ protection.
+
+ The option is available when `CONFIG_XEN_SHSTK` is compiled in, and
+- defaults to `true` on hardware supporting CET-SS. Specifying
++ generally defaults to `true` on hardware supporting CET-SS. Specifying
+ `cet=no-shstk` will cause Xen not to use Shadow Stacks even when support
+ is available in hardware.
+
++ Some hardware suffers from an issue known as Supervisor Shadow Stack
++ Fracturing. On such hardware, Xen will default to not using Shadow Stacks
++ when virtualised. Specifying `cet=shstk` will override this heuristic and
++ enable Shadow Stacks unilaterally.
++
+ * The `ibt=` boolean controls whether Xen uses Indirect Branch Tracking for
+ its own protection.
+
+diff --git a/tools/libs/light/libxl_cpuid.c b/tools/libs/light/libxl_cpuid.c
+index 2aa23225f4..d97a2f3338 100644
+--- a/tools/libs/light/libxl_cpuid.c
++++ b/tools/libs/light/libxl_cpuid.c
+@@ -235,6 +235,8 @@ int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str)
+ {"fsrs", 0x00000007, 1, CPUID_REG_EAX, 11, 1},
+ {"fsrcs", 0x00000007, 1, CPUID_REG_EAX, 12, 1},
+
++ {"cet-sss", 0x00000007, 1, CPUID_REG_EDX, 18, 1},
++
+ {"intel-psfd", 0x00000007, 2, CPUID_REG_EDX, 0, 1},
+ {"mcdt-no", 0x00000007, 2, CPUID_REG_EDX, 5, 1},
+
+diff --git a/tools/misc/xen-cpuid.c b/tools/misc/xen-cpuid.c
+index addb3a39a1..0248eaef44 100644
+--- a/tools/misc/xen-cpuid.c
++++ b/tools/misc/xen-cpuid.c
+@@ -208,6 +208,7 @@ static const char *const str_7c1[32] =
+
+ static const char *const str_7d1[32] =
+ {
++ [18] = "cet-sss",
+ };
+
+ static const char *const str_7d2[32] =
+diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
+index b3fcf4680f..27f73d3bbe 100644
+--- a/xen/arch/x86/cpu/common.c
++++ b/xen/arch/x86/cpu/common.c
+@@ -346,11 +346,18 @@ void __init early_cpu_init(void)
+ x86_cpuid_vendor_to_str(c->x86_vendor), c->x86, c->x86,
+ c->x86_model, c->x86_model, c->x86_mask, eax);
+
+- if (c->cpuid_level >= 7)
+- cpuid_count(7, 0, &eax, &ebx,
++ if (c->cpuid_level >= 7) {
++ uint32_t max_subleaf;
++
++ cpuid_count(7, 0, &max_subleaf, &ebx,
+ &c->x86_capability[FEATURESET_7c0],
+ &c->x86_capability[FEATURESET_7d0]);
+
++ if (max_subleaf >= 1)
++ cpuid_count(7, 1, &eax, &ebx, &ecx,
++ &c->x86_capability[FEATURESET_7d1]);
++ }
++
+ eax = cpuid_eax(0x80000000);
+ if ((eax >> 16) == 0x8000 && eax >= 0x80000008) {
+ ebx = eax >= 0x8000001f ? cpuid_ebx(0x8000001f) : 0;
+diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
+index e05189f649..09c17b1016 100644
+--- a/xen/arch/x86/setup.c
++++ b/xen/arch/x86/setup.c
+@@ -95,11 +95,7 @@ unsigned long __initdata highmem_start;
+ size_param("highmem-start", highmem_start);
+ #endif
+
+-#ifdef CONFIG_XEN_SHSTK
+-static bool __initdata opt_xen_shstk = true;
+-#else
+-#define opt_xen_shstk false
+-#endif
++static int8_t __initdata opt_xen_shstk = -IS_ENABLED(CONFIG_XEN_SHSTK);
+
+ #ifdef CONFIG_XEN_IBT
+ static bool __initdata opt_xen_ibt = true;
+@@ -1104,11 +1100,45 @@ void __init noreturn __start_xen(unsigned long mbi_p)
+ early_cpu_init();
+
+ /* Choose shadow stack early, to set infrastructure up appropriately. */
+- if ( opt_xen_shstk && boot_cpu_has(X86_FEATURE_CET_SS) )
++ if ( !boot_cpu_has(X86_FEATURE_CET_SS) )
++ opt_xen_shstk = 0;
++
++ if ( opt_xen_shstk )
+ {
+- printk("Enabling Supervisor Shadow Stacks\n");
++ /*
++ * Some CPUs suffer from Shadow Stack Fracturing, an issue whereby a
++ * fault/VMExit/etc between setting a Supervisor Busy bit and the
++ * event delivery completing renders the operation non-restartable.
++ * On restart, event delivery will find the Busy bit already set.
++ *
++ * This is a problem on bare metal, but outside of synthetic cases or
++ * a very badly timed #MC, it's not believed to be a problem. It is a
++ * much bigger problem under virt, because we can VMExit for a number
++ * of legitimate reasons and tickle this bug.
++ *
++ * CPUs with this addressed enumerate CET-SSS to indicate that
++ * supervisor shadow stacks are now safe to use.
++ */
++ bool cpu_has_bug_shstk_fracture =
++ boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
++ !boot_cpu_has(X86_FEATURE_CET_SSS);
+
+- setup_force_cpu_cap(X86_FEATURE_XEN_SHSTK);
++ /*
++ * On bare metal, assume that Xen won't be impacted by shstk
++ * fracturing problems. Under virt, be more conservative and disable
++ * shstk by default.
++ */
++ if ( opt_xen_shstk == -1 )
++ opt_xen_shstk =
++ cpu_has_hypervisor ? !cpu_has_bug_shstk_fracture
++ : true;
++
++ if ( opt_xen_shstk )
++ {
++ printk("Enabling Supervisor Shadow Stacks\n");
++
++ setup_force_cpu_cap(X86_FEATURE_XEN_SHSTK);
++ }
+ }
+
+ if ( opt_xen_ibt && boot_cpu_has(X86_FEATURE_CET_IBT) )
+diff --git a/xen/include/public/arch-x86/cpufeatureset.h b/xen/include/public/arch-x86/cpufeatureset.h
+index f43cdcd0f9..08600cfdc7 100644
+--- a/xen/include/public/arch-x86/cpufeatureset.h
++++ b/xen/include/public/arch-x86/cpufeatureset.h
+@@ -298,6 +298,7 @@ XEN_CPUFEATURE(MCDT_NO, 13*32+ 5) /*A MCDT_NO */
+ /* Intel-defined CPU features, CPUID level 0x00000007:1.ecx, word 14 */
+
+ /* Intel-defined CPU features, CPUID level 0x00000007:1.edx, word 15 */
++XEN_CPUFEATURE(CET_SSS, 15*32+18) /* CET Supervisor Shadow Stacks safe to use */
+
+ #endif /* XEN_CPUFEATURE */
+
+--
+2.40.0
+