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.
{"fsrcs", 0x00000007, 1, CPUID_REG_EAX, 12, 1},
{"wrmsrns", 0x00000007, 1, CPUID_REG_EAX, 19, 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},
static const char *const str_7d1[32] =
{
+ [18] = "cet-sss",
};
static const char *const str_7d2[32] =
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;
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;
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) )
/* 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 */