Xen Test Framework
main.c
Go to the documentation of this file.
1
33#include <xtf.h>
34
35const char test_title[] = "XSA-339 PoC";
36
37void entry_GP(void);
38
39static 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
65static 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
74void do_sysenter(struct cpu_regs *regs)
75{
77}
78
79bool 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
106 return true;
107 }
108
109 return false;
110}
111
112void test_main(void)
113{
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 */
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_SP
Definition: asm_macros.h:37
#define _ASM_CX
Definition: asm_macros.h:34
#define __user_text
Definition: compiler.h:33
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(vec, ec)
Definition: exinfo.h:26
#define EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
#define EXINFO_AVAIL0
Definition: exinfo.h:24
unsigned int exinfo_t
Packed exception and error code information.
Definition: exinfo.h:19
#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
#define STR(x)
Stringise an expression, expanding preprocessor tokens.
Definition: macro_magic.h:17
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
#define GP
bool do_unhandled_exception(struct cpu_regs *regs)
May be implemented by a guest to provide custom exception handling.
Definition: main.c:93
#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 X86_SEL_RPL_MASK
Definition: processor.h:189
#define X86_EFLAGS_NT
Definition: processor.h:18
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
static void fixup_sysenter_state(struct cpu_regs *regs)
Definition: main.c:65
static unsigned long sysenter_nt(void)
Definition: main.c:39
void entry_GP(void)
void do_sysenter(struct cpu_regs *regs)
May be implemented by a guest to handle SYSENTER invocations.
Definition: main.c:74