FRED doesn't use Supervisor Shadow Stack tokens. This means that:
1) memguard_guard_stack() should not write Supervisor Shadow Stack Tokens.
2) cpu_has_bug_shstk_fracture is no longer relevant when deciding whether or
not to enable Shadow Stacks in the first place.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
v4:
* Adjust for cpu_has_bug_shstk_fracture.
* Reworked entirely in light of the prior 3 patches.
The SDM explicitly points out the shstk fracture vs FRED case, yet PTL
enumerates CET-SSS (immunity to shstk fracture). I can only assume that there
are other Intel CPUs with FRED but without CET-SSS.
---
xen/arch/x86/mm.c | 14 +++++++++++---
xen/arch/x86/setup.c | 16 ++++++++++------
2 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 0d0d5292953b..4c404b6c134f 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -129,6 +129,7 @@
#include <asm/shadow.h>
#include <asm/shared.h>
#include <asm/trampoline.h>
+#include <asm/traps.h>
#include <asm/x86_emulate.h>
#include <public/memory.h>
@@ -6441,8 +6442,15 @@ static void write_sss_token(unsigned long *ptr)
void memguard_guard_stack(void *p)
{
- /* IST Shadow stacks. 4x 1k in stack page 0. */
- if ( IS_ENABLED(CONFIG_XEN_SHSTK) )
+ ASSERT(opt_fred >= 0); /* Confirm that FRED-ness has been resolved */
+
+ /*
+ * IST Shadow stacks. 4x 1k in stack page 0.
+ *
+ * With IDT delivery, we need Supervisor Shadow Stack tokens at the base
+ * of each stack. With FRED delivery, these no longer exist.
+ */
+ if ( IS_ENABLED(CONFIG_XEN_SHSTK) && !opt_fred )
{
write_sss_token(p + (IST_MCE * IST_SHSTK_SIZE) - 8);
write_sss_token(p + (IST_NMI * IST_SHSTK_SIZE) - 8);
@@ -6453,7 +6461,7 @@ void memguard_guard_stack(void *p)
/* Primary Shadow Stack. 1x 4k in stack page 5. */
p += PRIMARY_SHSTK_SLOT * PAGE_SIZE;
- if ( IS_ENABLED(CONFIG_XEN_SHSTK) )
+ if ( IS_ENABLED(CONFIG_XEN_SHSTK) && !opt_fred )
write_sss_token(p + PAGE_SIZE - 8);
map_pages_to_xen((unsigned long)p, virt_to_mfn(p), 1, PAGE_HYPERVISOR_SHSTK);
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 0816a713e1c8..8e59c9801afe 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1412,15 +1412,19 @@ void asmlinkage __init noreturn __start_xen(void)
boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
!boot_cpu_has(X86_FEATURE_CET_SSS);
+ ASSERT(opt_fred >= 0); /* Confirm that FRED-ness has been resolved */
+
/*
- * 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 FRED is in use, Supervisor Shadow Stack tokens are not used and
+ * shstk fracturing is of no consequence. Otherwise:
+ * - 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;
+ opt_fred || (cpu_has_hypervisor ? !cpu_has_bug_shstk_fracture
+ : true);
if ( opt_xen_shstk )
{
@@ -1925,7 +1929,7 @@ void asmlinkage __init noreturn __start_xen(void)
system_state = SYS_STATE_boot;
- bsp_stack = cpu_alloc_stack(0);
+ bsp_stack = cpu_alloc_stack(0); /* Needs to know IDT vs FRED */
if ( !bsp_stack )
panic("No memory for BSP stack\n");
--
2.39.5