Skip to content

Commit

Permalink
x86/shstk: Activate Supervisor Shadow Stacks
Browse files Browse the repository at this point in the history
With all other plumbing in place, activate shadow stacks when possible.

Note that CET shares the similar problems to SMEP/SMAP with Ring1 being
supervisor to the processor, and that the layout of the shadow stack differs
between an IRET to Ring 1 and Ring 3.  Therefore, we disable PV32 when CET is
enabled.  Compatibility can be maintained if necessary via PV-Shim.

The BSP needs to wait until alternatives have run (to avoid interaction with
CR0.WP), and after the first reset_stack_and_jump() to avoid having a pristine
shadow stack interact in problematic ways with an in-use regular stack.
Activate shadow stack in reinit_bsp_stack().

APs have all infrastructure set up by the booting CPU, so enable shadow stacks
before entering C.  Adjust the logic to call start_secondary rather than jump
to it, so stack traces make more sense.

The crash path needs to turn CET off to avoid interfering with the crash
kernel's environment.

Signed-off-by: Andrew Cooper <[email protected]>
Reviewed-by: Jan Beulich <[email protected]>
  • Loading branch information
andyhhp committed May 29, 2020
1 parent 633ecc4 commit b60ab42
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 2 deletions.
8 changes: 8 additions & 0 deletions docs/misc/xen-command-line.pandoc
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ call/jmp COP/JOP) attacks.
`cet=no-shstk` will cause Xen not to use Shadow Stacks even when support
is available in hardware.

Shadow Stacks are incompatible with 32bit PV guests. This option will
override the `pv=32` boolean to false. Backwards compatibility can be
maintained with the `pv-shim` mechanism.

### clocksource (x86)
> `= pit | hpet | acpi | tsc`

Expand Down Expand Up @@ -1726,6 +1730,10 @@ Controls for aspects of PV guest support.
* The `32` boolean controls whether 32bit PV guests can be created. It
defaults to `true`, and is ignored when `CONFIG_PV32` is compiled out.

32bit PV guests are incompatible with CET Shadow Stacks. If Xen is using
shadow stacks, this option will be overridden to `false`. Backwards
compatibility can be maintained with the `pv-shim` mechanism.

### pv-linear-pt (x86)
> `= <boolean>`

Expand Down
35 changes: 33 additions & 2 deletions xen/arch/x86/boot/x86_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,39 @@ ENTRY(__high_start)
lretq
1:
test %ebx,%ebx
jnz start_secondary

jz .L_bsp

/* APs. Set up shadow stacks before entering C. */

testl $cpufeat_mask(X86_FEATURE_XEN_SHSTK), \
CPUINFO_FEATURE_OFFSET(X86_FEATURE_XEN_SHSTK) + boot_cpu_data(%rip)
je .L_ap_shstk_done

/* Set up MSR_S_CET. */
mov $MSR_S_CET, %ecx
xor %edx, %edx
mov $CET_SHSTK_EN | CET_WRSS_EN, %eax
wrmsr

/* Derive MSR_PL0_SSP from %rsp (token written when stack is allocated). */
mov $MSR_PL0_SSP, %ecx
mov %rsp, %rdx
shr $32, %rdx
mov %esp, %eax
and $~(STACK_SIZE - 1), %eax
or $(PRIMARY_SHSTK_SLOT + 1) * PAGE_SIZE - 8, %eax
wrmsr

/* Enable CET. MSR_INTERRUPT_SSP_TABLE is set up later in load_system_tables(). */
mov $XEN_MINIMAL_CR4 | X86_CR4_CET, %ecx
mov %rcx, %cr4
setssbsy

.L_ap_shstk_done:
call start_secondary
BUG /* start_secondary() shouldn't return. */

.L_bsp:
/* Pass off the Multiboot info structure to C land (if applicable). */
mov multiboot_ptr(%rip),%edi
call __start_xen
Expand Down
5 changes: 5 additions & 0 deletions xen/arch/x86/cpu/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,11 @@ 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, &ecx, &edx);
c->x86_capability[cpufeat_word(X86_FEATURE_CET_SS)] = ecx;
}

eax = cpuid_eax(0x80000000);
if ((eax >> 16) == 0x8000 && eax >= 0x80000008) {
eax = cpuid_eax(0x80000008);
Expand Down
7 changes: 7 additions & 0 deletions xen/arch/x86/crash.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,13 @@ void machine_crash_shutdown(void)
/* Reset CPUID masking and faulting to the host's default. */
ctxt_switch_levelling(NULL);

/* Disable shadow stacks. */
if ( cpu_has_xen_shstk )
{
wrmsrl(MSR_S_CET, 0);
write_cr4(read_cr4() & ~X86_CR4_CET);
}

info = kexec_crash_save_info();
info->xen_phys_start = xen_phys_start;
info->dom0_pfn_to_mfn_frame_list_list =
Expand Down
27 changes: 27 additions & 0 deletions xen/arch/x86/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,14 @@ static void __init noreturn reinit_bsp_stack(void)
stack_base[0] = stack;
memguard_guard_stack(stack);

if ( cpu_has_xen_shstk )
{
wrmsrl(MSR_PL0_SSP,
(unsigned long)stack + (PRIMARY_SHSTK_SLOT + 1) * PAGE_SIZE - 8);
wrmsrl(MSR_S_CET, CET_SHSTK_EN | CET_WRSS_EN);
asm volatile ("setssbsy" ::: "memory");
}

reset_stack_and_jump_nolp(init_done);
}

Expand Down Expand Up @@ -1065,6 +1073,21 @@ void __init noreturn __start_xen(unsigned long mbi_p)
/* This must come before e820 code because it sets paddr_bits. */
early_cpu_init();

/* Choose shadow stack early, to set infrastructure up appropriately. */
if ( opt_xen_shstk && boot_cpu_has(X86_FEATURE_CET_SS) )
{
printk("Enabling Supervisor Shadow Stacks\n");

setup_force_cpu_cap(X86_FEATURE_XEN_SHSTK);
#ifdef CONFIG_PV32
if ( opt_pv32 )
{
opt_pv32 = 0;
printk(" - Disabling PV32 due to Shadow Stacks\n");
}
#endif
}

/* Sanitise the raw E820 map to produce a final clean version. */
max_page = raw_max_page = init_e820(memmap_type, &e820_raw);

Expand Down Expand Up @@ -1801,6 +1824,10 @@ void __init noreturn __start_xen(unsigned long mbi_p)

alternative_branches();

/* Defer CR4.CET until alternatives have finished playing with CR0.WP */
if ( cpu_has_xen_shstk )
set_in_cr4(X86_CR4_CET);

/*
* NB: when running as a PV shim VCPUOP_up/down is wired to the shim
* physical cpu_add/remove functions, so launch the guest with only
Expand Down
8 changes: 8 additions & 0 deletions xen/arch/x86/spec_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,14 @@ void __init init_speculation_mitigations(void)

hw_smt_enabled = check_smt_enabled();

/*
* First, disable the use of retpolines if Xen is using shadow stacks, as
* they are incompatible.
*/
if ( cpu_has_xen_shstk &&
(opt_thunk == THUNK_DEFAULT || opt_thunk == THUNK_RETPOLINE) )
thunk = THUNK_JMP;

/*
* Has the user specified any custom BTI mitigations? If so, follow their
* instructions exactly and disable all heuristics.
Expand Down

0 comments on commit b60ab42

Please sign in to comment.