mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
x86/traps: Implement #CP handler and extend #PF for shadow stacks
For now, any #CP exception or shadow stack #PF indicate a bug in Xen, but attempt to recover from #CP if taken in guest context. This will of course have to change as part of introducing CET-SS support for PV guests. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
d3fb3ed32f
commit
5ad05b9c24
3 files changed
+53
-2
No files matched your search
+45
-1
@@ -156,7 +156,9 @@ void (* const exception_table[TRAP_nr])(struct cpu_user_regs *regs) = {
|
||||
[TRAP_alignment_check] = do_trap,
|
||||
[TRAP_machine_check] = (void *)do_machine_check,
|
||||
[TRAP_simd_error] = do_trap,
|
||||
[TRAP_virtualisation ...
|
||||
[TRAP_virtualisation] = do_reserved_trap,
|
||||
[X86_EXC_CP] = do_entry_CP,
|
||||
[X86_EXC_CP + 1 ...
|
||||
(ARRAY_SIZE(exception_table) - 1)] = do_reserved_trap,
|
||||
};
|
||||
|
||||
@@ -1431,6 +1433,10 @@ void do_page_fault(struct cpu_user_regs *regs)
|
||||
|
||||
perfc_incr(page_faults);
|
||||
|
||||
/* Any shadow stack access fault is a bug in Xen. */
|
||||
if ( error_code & PFEC_shstk )
|
||||
goto fatal;
|
||||
|
||||
if ( unlikely(fixup_page_fault(addr, regs) != 0) )
|
||||
return;
|
||||
|
||||
@@ -1898,6 +1904,43 @@ void do_debug(struct cpu_user_regs *regs)
|
||||
pv_inject_hw_exception(TRAP_debug, X86_EVENT_NO_EC);
|
||||
}
|
||||
|
||||
void do_entry_CP(struct cpu_user_regs *regs)
|
||||
{
|
||||
static const char errors[][10] = {
|
||||
[1] = "near ret",
|
||||
[2] = "far/iret",
|
||||
[3] = "endbranch",
|
||||
[4] = "rstorssp",
|
||||
[5] = "setssbsy",
|
||||
};
|
||||
const char *err = "??";
|
||||
unsigned int ec = regs->error_code;
|
||||
|
||||
if ( debugger_trap_entry(TRAP_debug, regs) )
|
||||
return;
|
||||
|
||||
/* Decode ec if possible */
|
||||
if ( ec < ARRAY_SIZE(errors) && errors[ec][0] )
|
||||
err = errors[ec];
|
||||
|
||||
/*
|
||||
* For now, only supervisors shadow stacks should be active. A #CP from
|
||||
* guest context is probably a Xen bug, but kill the guest in an attempt
|
||||
* to recover.
|
||||
*/
|
||||
if ( guest_mode(regs) )
|
||||
{
|
||||
gprintk(XENLOG_ERR, "Hit #CP[%04x] in guest context %04x:%p\n",
|
||||
ec, regs->cs, _p(regs->rip));
|
||||
ASSERT_UNREACHABLE();
|
||||
domain_crash(current->domain);
|
||||
return;
|
||||
}
|
||||
|
||||
show_execution_state(regs);
|
||||
panic("CONTROL-FLOW PROTECTION FAULT: #CP[%04x] %s\n", ec, err);
|
||||
}
|
||||
|
||||
static void __init noinline __set_intr_gate(unsigned int n,
|
||||
uint32_t dpl, void *addr)
|
||||
{
|
||||
@@ -1987,6 +2030,7 @@ void __init init_idt_traps(void)
|
||||
set_intr_gate(TRAP_alignment_check,&alignment_check);
|
||||
set_intr_gate(TRAP_machine_check,&machine_check);
|
||||
set_intr_gate(TRAP_simd_error,&simd_coprocessor_error);
|
||||
set_intr_gate(X86_EXC_CP, entry_CP);
|
||||
|
||||
/* Specify dedicated interrupt stacks for NMI, #DF, and #MC. */
|
||||
enable_each_ist(idt_table);
|
||||
|
||||
@@ -795,6 +795,10 @@ ENTRY(alignment_check)
|
||||
movl $TRAP_alignment_check,4(%rsp)
|
||||
jmp handle_exception
|
||||
|
||||
ENTRY(entry_CP)
|
||||
movl $X86_EXC_CP, 4(%rsp)
|
||||
jmp handle_exception
|
||||
|
||||
ENTRY(double_fault)
|
||||
movl $TRAP_double_fault,4(%rsp)
|
||||
/* Set AC to reduce chance of further SMAP faults */
|
||||
@@ -940,7 +944,8 @@ autogen_stubs: /* Automatically generated stubs. */
|
||||
entrypoint 1b
|
||||
|
||||
/* Reserved exceptions, heading towards do_reserved_trap(). */
|
||||
.elseif vec == TRAP_copro_seg || vec == TRAP_spurious_int || (vec > TRAP_simd_error && vec < TRAP_nr)
|
||||
.elseif vec == X86_EXC_CSO || vec == X86_EXC_SPV || \
|
||||
vec == X86_EXC_VE || (vec > X86_EXC_CP && vec < TRAP_nr)
|
||||
|
||||
1: test $8,%spl /* 64bit exception frames are 16 byte aligned, but the word */
|
||||
jz 2f /* size is 8 bytes. Check whether the processor gave us an */
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
#define PFEC_reserved_bit (_AC(1,U) << 3)
|
||||
#define PFEC_insn_fetch (_AC(1,U) << 4)
|
||||
#define PFEC_prot_key (_AC(1,U) << 5)
|
||||
#define PFEC_shstk (_AC(1,U) << 6)
|
||||
#define PFEC_arch_mask (_AC(0xffff,U)) /* Architectural PFEC values. */
|
||||
/* Internally used only flags. */
|
||||
#define PFEC_page_paged (1U<<16)
|
||||
@@ -535,6 +536,7 @@ DECLARE_TRAP_HANDLER(coprocessor_error);
|
||||
DECLARE_TRAP_HANDLER(simd_coprocessor_error);
|
||||
DECLARE_TRAP_HANDLER_CONST(machine_check);
|
||||
DECLARE_TRAP_HANDLER(alignment_check);
|
||||
DECLARE_TRAP_HANDLER(entry_CP);
|
||||
|
||||
DECLARE_TRAP_HANDLER(entry_int82);
|
||||
|
||||
|
||||