[PATCH v4 1/4] x86: record SSP at non-guest entry points
Jan Beulich <[email protected]>
| Newsgroups | org.xenproject.lists.xen-devel |
|---|---|
| Message-ID | <[email protected]> |
We will want to use that value for call trace generation, and likely also to eliminate the somewhat fragile shadow stack searching done in fixup_exception_return(). For those purposes, guest-only entry points do not need to record that value. To keep the saving code simple, record our own SSP that corresponds to an exception frame, pointing to the top of the shadow stack counterpart of what the CPU has saved on the regular stack. Consuming code can then work its way from there. In SAVE_ALL / RESTORE_ALL simply drop the use of UREGS_r15. We want the full size in all cases, so what exactly the top-of-stack field is going to be (whose UREGS_* is 0 anyway) doesn't matter this much there. This way we don't need to distinguish between XEN_SHSTK=y and XEN_SHSTK=n. Signed-off-by: Jan Beulich <[email protected]> --- v4: Re-base. v3: Put new field at the front of struct cpu_user_regs. v2: Add comment ahead of SAVE_ALL. Add comma between its parameters. Re-base. --- a/xen/arch/x86/hvm/svm/entry.S +++ b/xen/arch/x86/hvm/svm/entry.S @@ -89,7 +89,7 @@ __UNLIKELY_END(nsvm_hap) vmrun - PUSH_AND_CLEAR_GPRS + PUSH_AND_CLEAR_GPRS ssp=0 GET_CURRENT(bx) --- a/xen/arch/x86/hvm/vmx/entry.S +++ b/xen/arch/x86/hvm/vmx/entry.S @@ -22,7 +22,7 @@ #include <asm/page.h> FUNC(vmx_asm_vmexit_handler) - PUSH_AND_CLEAR_GPRS + PUSH_AND_CLEAR_GPRS ssp=0 mov %cr2,%rax GET_CURRENT(bx) @@ -157,7 +157,7 @@ UNLIKELY_END(realmode) .Lvmx_vmentry_fail: sti - PUSH_AND_CLEAR_GPRS + PUSH_AND_CLEAR_GPRS ssp=0 /* * SPEC_CTRL_ENTRY notes --- a/xen/arch/x86/include/asm/asm_defns.h +++ b/xen/arch/x86/include/asm/asm_defns.h @@ -220,9 +220,11 @@ static always_inline void stac(void) #ifdef __ASSEMBLER__ /* - * Push and clear GPRs + * Push and clear GPRs. + * + * Use sites may override ssp to 0. It should never be overridden to 1. */ -.macro PUSH_AND_CLEAR_GPRS +.macro PUSH_AND_CLEAR_GPRS ssp=IS_ENABLED(CONFIG_XEN_SHSTK) push %rdi xor %edi, %edi push %rsi @@ -233,6 +235,9 @@ static always_inline void stac(void) xor %ecx, %ecx push %rax xor %eax, %eax + .if \ssp + rdsspq %rcx + .endif push %r8 xor %r8d, %r8d push %r9 @@ -259,12 +264,18 @@ static always_inline void stac(void) xor %r14d, %r14d push %r15 xor %r15d, %r15d +#ifdef CONFIG_XEN_SHSTK + push %rcx +#endif .endm /* * POP GPRs from a UREGS_* frame on the stack. Does not modify flags. */ .macro POP_GPRS skip_rax=0 +#ifdef CONFIG_XEN_SHSTK + pop %rcx +#endif pop %r15 pop %r14 pop %r13 --- a/xen/arch/x86/include/asm/cpu-user-regs.h +++ b/xen/arch/x86/include/asm/cpu-user-regs.h @@ -11,6 +11,15 @@ */ struct cpu_user_regs { +#ifdef CONFIG_XEN_SHSTK + /* + * This points _at_ the corresponding shadow stack frame; it is _not_ the + * outer context's SSP. That, if the outer context has CET-SS enabled, + * is stored in the top slot of the pointed to shadow stack. + */ + uint64_t entry_ssp; +#endif + union { uint64_t r15; uint32_t r15d; uint16_t r15w; uint8_t r15b; }; union { uint64_t r14; uint32_t r14d; uint16_t r14w; uint8_t r14b; }; union { uint64_t r13; uint32_t r13d; uint16_t r13w; uint8_t r13b; }; --- a/xen/arch/x86/x86_64/asm-offsets.c +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -53,6 +53,9 @@ void __dummy__(void) OFFSET(UREGS_eflags, struct cpu_user_regs, rflags); OFFSET(UREGS_rsp, struct cpu_user_regs, rsp); OFFSET(UREGS_ss, struct cpu_user_regs, ss); +#ifdef CONFIG_XEN_SHSTK + OFFSET(UREGS_entry_ssp, struct cpu_user_regs, entry_ssp); +#endif DEFINE(UREGS_kernel_sizeof, sizeof(struct cpu_user_regs)); BLANK(); --- a/xen/arch/x86/x86_64/compat/entry.S +++ b/xen/arch/x86/x86_64/compat/entry.S @@ -18,7 +18,7 @@ FUNC(entry_int82) ALTERNATIVE "", clac, X86_FEATURE_XEN_SMAP pushq $0 movb $HYPERCALL_VECTOR, EFRAME_entry_vector(%rsp) - PUSH_AND_CLEAR_GPRS + PUSH_AND_CLEAR_GPRS ssp=0 GET_STACK_END(14) --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -305,7 +305,7 @@ FUNC(lstar_enter) pushq $0 BUILD_BUG_ON(TRAP_syscall & 0xff) movb $TRAP_syscall >> 8, EFRAME_entry_vector + 1(%rsp) - PUSH_AND_CLEAR_GPRS + PUSH_AND_CLEAR_GPRS ssp=0 GET_STACK_END(14) @@ -345,7 +345,7 @@ FUNC(cstar_enter) pushq $0 BUILD_BUG_ON(TRAP_syscall & 0xff) movb $TRAP_syscall >> 8, EFRAME_entry_vector + 1(%rsp) - PUSH_AND_CLEAR_GPRS + PUSH_AND_CLEAR_GPRS ssp=0 GET_STACK_END(14) @@ -390,7 +390,7 @@ LABEL(sysenter_eflags_saved, 0) pushq $0 BUILD_BUG_ON(TRAP_syscall & 0xff) movb $TRAP_syscall >> 8, EFRAME_entry_vector + 1(%rsp) - PUSH_AND_CLEAR_GPRS + PUSH_AND_CLEAR_GPRS ssp=0 GET_STACK_END(14) @@ -447,7 +447,7 @@ FUNC(entry_int80) ALTERNATIVE "", clac, X86_FEATURE_XEN_SMAP pushq $0 movb $0x80, EFRAME_entry_vector(%rsp) - PUSH_AND_CLEAR_GPRS + PUSH_AND_CLEAR_GPRS ssp=0 GET_STACK_END(14) --- a/xen/arch/x86/x86_64/entry-fred.S +++ b/xen/arch/x86/x86_64/entry-fred.S @@ -11,7 +11,7 @@ /* The Ring3 entry point is required to be 4k aligned. */ FUNC(entry_FRED_R3, 4096) - PUSH_AND_CLEAR_GPRS + PUSH_AND_CLEAR_GPRS ssp=0 mov %rsp, %rdi call entry_from_pv @@ -54,7 +54,7 @@ LABEL(eretu, 0) END(eretu_exit_to_guest) FUNC(eretu_error_dom_crash) - PUSH_AND_CLEAR_GPRS + PUSH_AND_CLEAR_GPRS ssp=0 sti call asm_domain_crash_synchronous /* Does not return */ END(eretu_error_dom_crash)