diff options
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.patch | 195 |
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 + |