]> git.proxmox.com Git - pve-kernel.git/blob - patches/kernel/0029-x86-xen-Get-rid-of-paravirt-op-adjust_exception_fram.patch
revert buggy SCSI error handler commit
[pve-kernel.git] / patches / kernel / 0029-x86-xen-Get-rid-of-paravirt-op-adjust_exception_fram.patch
1 From e5688fb8c2c243658f3fe754d33c7250c8aed146 Mon Sep 17 00:00:00 2001
2 From: Juergen Gross <jgross@suse.com>
3 Date: Thu, 31 Aug 2017 19:42:49 +0200
4 Subject: [PATCH 029/242] x86/xen: Get rid of paravirt op
5 adjust_exception_frame
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 CVE-2017-5754
11
12 When running as Xen pv-guest the exception frame on the stack contains
13 %r11 and %rcx additional to the other data pushed by the processor.
14
15 Instead of having a paravirt op being called for each exception type
16 prepend the Xen specific code to each exception entry. When running as
17 Xen pv-guest just use the exception entry with prepended instructions,
18 otherwise use the entry without the Xen specific code.
19
20 [ tglx: Merged through tip to avoid ugly merge conflict ]
21
22 Signed-off-by: Juergen Gross <jgross@suse.com>
23 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
24 Cc: xen-devel@lists.xenproject.org
25 Cc: boris.ostrovsky@oracle.com
26 Cc: luto@amacapital.net
27 Link: http://lkml.kernel.org/r/20170831174249.26853-1-jg@pfupf.net
28 (backported from commit 5878d5d6fdef6447d73b0acc121ba445bef37f53)
29 Signed-off-by: Andy Whitcroft <apw@canonical.com>
30 Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
31 (cherry picked from commit 9a6fb927deb3ebbe831741ca82081714637181a7)
32 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
33 ---
34 arch/x86/include/asm/paravirt.h | 5 --
35 arch/x86/include/asm/paravirt_types.h | 3 --
36 arch/x86/include/asm/proto.h | 3 ++
37 arch/x86/include/asm/traps.h | 28 ++++++++--
38 arch/x86/xen/xen-ops.h | 1 -
39 arch/x86/kernel/asm-offsets_64.c | 1 -
40 arch/x86/kernel/paravirt.c | 3 --
41 arch/x86/xen/enlighten_pv.c | 98 +++++++++++++++++++++++------------
42 arch/x86/xen/irq.c | 3 --
43 arch/x86/entry/entry_64.S | 23 ++------
44 arch/x86/entry/entry_64_compat.S | 1 -
45 arch/x86/xen/xen-asm_64.S | 41 +++++++++++++--
46 12 files changed, 133 insertions(+), 77 deletions(-)
47
48 diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
49 index 9ccac1926587..c25dd22f7c70 100644
50 --- a/arch/x86/include/asm/paravirt.h
51 +++ b/arch/x86/include/asm/paravirt.h
52 @@ -960,11 +960,6 @@ extern void default_banner(void);
53 #define GET_CR2_INTO_RAX \
54 call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2)
55
56 -#define PARAVIRT_ADJUST_EXCEPTION_FRAME \
57 - PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_adjust_exception_frame), \
58 - CLBR_NONE, \
59 - call PARA_INDIRECT(pv_irq_ops+PV_IRQ_adjust_exception_frame))
60 -
61 #define USERGS_SYSRET64 \
62 PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64), \
63 CLBR_NONE, \
64 diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
65 index 9ffc36bfe4cd..6b64fc6367f2 100644
66 --- a/arch/x86/include/asm/paravirt_types.h
67 +++ b/arch/x86/include/asm/paravirt_types.h
68 @@ -196,9 +196,6 @@ struct pv_irq_ops {
69 void (*safe_halt)(void);
70 void (*halt)(void);
71
72 -#ifdef CONFIG_X86_64
73 - void (*adjust_exception_frame)(void);
74 -#endif
75 } __no_randomize_layout;
76
77 struct pv_mmu_ops {
78 diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h
79 index 8d3964fc5f91..b408b1886195 100644
80 --- a/arch/x86/include/asm/proto.h
81 +++ b/arch/x86/include/asm/proto.h
82 @@ -24,6 +24,9 @@ void entry_SYSENTER_compat(void);
83 void __end_entry_SYSENTER_compat(void);
84 void entry_SYSCALL_compat(void);
85 void entry_INT80_compat(void);
86 +#if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV)
87 +void xen_entry_INT80_compat(void);
88 +#endif
89 #endif
90
91 void x86_configure_nx(void);
92 diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
93 index b4f322d6c95f..feb89dbe359d 100644
94 --- a/arch/x86/include/asm/traps.h
95 +++ b/arch/x86/include/asm/traps.h
96 @@ -13,9 +13,6 @@ asmlinkage void divide_error(void);
97 asmlinkage void debug(void);
98 asmlinkage void nmi(void);
99 asmlinkage void int3(void);
100 -asmlinkage void xen_debug(void);
101 -asmlinkage void xen_int3(void);
102 -asmlinkage void xen_stack_segment(void);
103 asmlinkage void overflow(void);
104 asmlinkage void bounds(void);
105 asmlinkage void invalid_op(void);
106 @@ -56,6 +53,31 @@ asmlinkage void simd_coprocessor_error(void);
107 #define trace_page_fault page_fault
108 #endif
109
110 +#if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV)
111 +asmlinkage void xen_divide_error(void);
112 +asmlinkage void xen_xendebug(void);
113 +asmlinkage void xen_xenint3(void);
114 +asmlinkage void xen_nmi(void);
115 +asmlinkage void xen_overflow(void);
116 +asmlinkage void xen_bounds(void);
117 +asmlinkage void xen_invalid_op(void);
118 +asmlinkage void xen_device_not_available(void);
119 +asmlinkage void xen_double_fault(void);
120 +asmlinkage void xen_coprocessor_segment_overrun(void);
121 +asmlinkage void xen_invalid_TSS(void);
122 +asmlinkage void xen_segment_not_present(void);
123 +asmlinkage void xen_stack_segment(void);
124 +asmlinkage void xen_general_protection(void);
125 +asmlinkage void xen_page_fault(void);
126 +asmlinkage void xen_spurious_interrupt_bug(void);
127 +asmlinkage void xen_coprocessor_error(void);
128 +asmlinkage void xen_alignment_check(void);
129 +#ifdef CONFIG_X86_MCE
130 +asmlinkage void xen_machine_check(void);
131 +#endif /* CONFIG_X86_MCE */
132 +asmlinkage void xen_simd_coprocessor_error(void);
133 +#endif
134 +
135 dotraplinkage void do_divide_error(struct pt_regs *, long);
136 dotraplinkage void do_debug(struct pt_regs *, long);
137 dotraplinkage void do_nmi(struct pt_regs *, long);
138 diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
139 index 70301ac0d414..c8a6d224f7ed 100644
140 --- a/arch/x86/xen/xen-ops.h
141 +++ b/arch/x86/xen/xen-ops.h
142 @@ -138,7 +138,6 @@ __visible void xen_restore_fl_direct(unsigned long);
143 __visible void xen_iret(void);
144 __visible void xen_sysret32(void);
145 __visible void xen_sysret64(void);
146 -__visible void xen_adjust_exception_frame(void);
147
148 extern int xen_panic_handler_init(void);
149
150 diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c
151 index 99332f550c48..cf42206926af 100644
152 --- a/arch/x86/kernel/asm-offsets_64.c
153 +++ b/arch/x86/kernel/asm-offsets_64.c
154 @@ -20,7 +20,6 @@ static char syscalls_ia32[] = {
155 int main(void)
156 {
157 #ifdef CONFIG_PARAVIRT
158 - OFFSET(PV_IRQ_adjust_exception_frame, pv_irq_ops, adjust_exception_frame);
159 OFFSET(PV_CPU_usergs_sysret64, pv_cpu_ops, usergs_sysret64);
160 OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs);
161 BLANK();
162 diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
163 index bc0a849589bb..a14df9eecfed 100644
164 --- a/arch/x86/kernel/paravirt.c
165 +++ b/arch/x86/kernel/paravirt.c
166 @@ -319,9 +319,6 @@ __visible struct pv_irq_ops pv_irq_ops = {
167 .irq_enable = __PV_IS_CALLEE_SAVE(native_irq_enable),
168 .safe_halt = native_safe_halt,
169 .halt = native_halt,
170 -#ifdef CONFIG_X86_64
171 - .adjust_exception_frame = paravirt_nop,
172 -#endif
173 };
174
175 __visible struct pv_cpu_ops pv_cpu_ops = {
176 diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
177 index c76f5ff4d0d7..ae2a2e2d6362 100644
178 --- a/arch/x86/xen/enlighten_pv.c
179 +++ b/arch/x86/xen/enlighten_pv.c
180 @@ -586,6 +586,70 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
181 preempt_enable();
182 }
183
184 +#ifdef CONFIG_X86_64
185 +struct trap_array_entry {
186 + void (*orig)(void);
187 + void (*xen)(void);
188 + bool ist_okay;
189 +};
190 +
191 +static struct trap_array_entry trap_array[] = {
192 + { debug, xen_xendebug, true },
193 + { int3, xen_xenint3, true },
194 + { double_fault, xen_double_fault, true },
195 +#ifdef CONFIG_X86_MCE
196 + { machine_check, xen_machine_check, true },
197 +#endif
198 + { nmi, xen_nmi, true },
199 + { overflow, xen_overflow, false },
200 +#ifdef CONFIG_IA32_EMULATION
201 + { entry_INT80_compat, xen_entry_INT80_compat, false },
202 +#endif
203 + { page_fault, xen_page_fault, false },
204 + { divide_error, xen_divide_error, false },
205 + { bounds, xen_bounds, false },
206 + { invalid_op, xen_invalid_op, false },
207 + { device_not_available, xen_device_not_available, false },
208 + { coprocessor_segment_overrun, xen_coprocessor_segment_overrun, false },
209 + { invalid_TSS, xen_invalid_TSS, false },
210 + { segment_not_present, xen_segment_not_present, false },
211 + { stack_segment, xen_stack_segment, false },
212 + { general_protection, xen_general_protection, false },
213 + { spurious_interrupt_bug, xen_spurious_interrupt_bug, false },
214 + { coprocessor_error, xen_coprocessor_error, false },
215 + { alignment_check, xen_alignment_check, false },
216 + { simd_coprocessor_error, xen_simd_coprocessor_error, false },
217 +};
218 +
219 +static bool get_trap_addr(void **addr, unsigned int ist)
220 +{
221 + unsigned int nr;
222 + bool ist_okay = false;
223 +
224 + /*
225 + * Replace trap handler addresses by Xen specific ones.
226 + * Check for known traps using IST and whitelist them.
227 + * The debugger ones are the only ones we care about.
228 + * Xen will handle faults like double_fault, * so we should never see
229 + * them. Warn if there's an unexpected IST-using fault handler.
230 + */
231 + for (nr = 0; nr < ARRAY_SIZE(trap_array); nr++) {
232 + struct trap_array_entry *entry = trap_array + nr;
233 +
234 + if (*addr == entry->orig) {
235 + *addr = entry->xen;
236 + ist_okay = entry->ist_okay;
237 + break;
238 + }
239 + }
240 +
241 + if (WARN_ON(ist != 0 && !ist_okay))
242 + return false;
243 +
244 + return true;
245 +}
246 +#endif
247 +
248 static int cvt_gate_to_trap(int vector, const gate_desc *val,
249 struct trap_info *info)
250 {
251 @@ -598,40 +662,8 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
252
253 addr = gate_offset(val);
254 #ifdef CONFIG_X86_64
255 - /*
256 - * Look for known traps using IST, and substitute them
257 - * appropriately. The debugger ones are the only ones we care
258 - * about. Xen will handle faults like double_fault,
259 - * so we should never see them. Warn if
260 - * there's an unexpected IST-using fault handler.
261 - */
262 - if (addr == (unsigned long)debug)
263 - addr = (unsigned long)xen_debug;
264 - else if (addr == (unsigned long)int3)
265 - addr = (unsigned long)xen_int3;
266 - else if (addr == (unsigned long)stack_segment)
267 - addr = (unsigned long)xen_stack_segment;
268 - else if (addr == (unsigned long)double_fault) {
269 - /* Don't need to handle these */
270 + if (!get_trap_addr((void **)&addr, val->bits.ist))
271 return 0;
272 -#ifdef CONFIG_X86_MCE
273 - } else if (addr == (unsigned long)machine_check) {
274 - /*
275 - * when xen hypervisor inject vMCE to guest,
276 - * use native mce handler to handle it
277 - */
278 - ;
279 -#endif
280 - } else if (addr == (unsigned long)nmi)
281 - /*
282 - * Use the native version as well.
283 - */
284 - ;
285 - else {
286 - /* Some other trap using IST? */
287 - if (WARN_ON(val->bits.ist != 0))
288 - return 0;
289 - }
290 #endif /* CONFIG_X86_64 */
291 info->address = addr;
292
293 diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c
294 index 33e92955e09d..d4eff5676cfa 100644
295 --- a/arch/x86/xen/irq.c
296 +++ b/arch/x86/xen/irq.c
297 @@ -123,9 +123,6 @@ static const struct pv_irq_ops xen_irq_ops __initconst = {
298
299 .safe_halt = xen_safe_halt,
300 .halt = xen_halt,
301 -#ifdef CONFIG_X86_64
302 - .adjust_exception_frame = xen_adjust_exception_frame,
303 -#endif
304 };
305
306 void __init xen_init_irq_ops(void)
307 diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
308 index dfabcbf8e813..c12260ef3e4b 100644
309 --- a/arch/x86/entry/entry_64.S
310 +++ b/arch/x86/entry/entry_64.S
311 @@ -829,7 +829,6 @@ ENTRY(\sym)
312 .endif
313
314 ASM_CLAC
315 - PARAVIRT_ADJUST_EXCEPTION_FRAME
316
317 .ifeq \has_error_code
318 pushq $-1 /* ORIG_RAX: no syscall to restart */
319 @@ -975,7 +974,7 @@ ENTRY(do_softirq_own_stack)
320 ENDPROC(do_softirq_own_stack)
321
322 #ifdef CONFIG_XEN
323 -idtentry xen_hypervisor_callback xen_do_hypervisor_callback has_error_code=0
324 +idtentry hypervisor_callback xen_do_hypervisor_callback has_error_code=0
325
326 /*
327 * A note on the "critical region" in our callback handler.
328 @@ -1042,8 +1041,6 @@ ENTRY(xen_failsafe_callback)
329 movq 8(%rsp), %r11
330 addq $0x30, %rsp
331 pushq $0 /* RIP */
332 - pushq %r11
333 - pushq %rcx
334 UNWIND_HINT_IRET_REGS offset=8
335 jmp general_protection
336 1: /* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */
337 @@ -1074,9 +1071,8 @@ idtentry int3 do_int3 has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
338 idtentry stack_segment do_stack_segment has_error_code=1
339
340 #ifdef CONFIG_XEN
341 -idtentry xen_debug do_debug has_error_code=0
342 -idtentry xen_int3 do_int3 has_error_code=0
343 -idtentry xen_stack_segment do_stack_segment has_error_code=1
344 +idtentry xendebug do_debug has_error_code=0
345 +idtentry xenint3 do_int3 has_error_code=0
346 #endif
347
348 idtentry general_protection do_general_protection has_error_code=1
349 @@ -1240,20 +1236,9 @@ ENTRY(error_exit)
350 END(error_exit)
351
352 /* Runs on exception stack */
353 +/* XXX: broken on Xen PV */
354 ENTRY(nmi)
355 UNWIND_HINT_IRET_REGS
356 - /*
357 - * Fix up the exception frame if we're on Xen.
358 - * PARAVIRT_ADJUST_EXCEPTION_FRAME is guaranteed to push at most
359 - * one value to the stack on native, so it may clobber the rdx
360 - * scratch slot, but it won't clobber any of the important
361 - * slots past it.
362 - *
363 - * Xen is a different story, because the Xen frame itself overlaps
364 - * the "NMI executing" variable.
365 - */
366 - PARAVIRT_ADJUST_EXCEPTION_FRAME
367 -
368 /*
369 * We allow breakpoints in NMIs. If a breakpoint occurs, then
370 * the iretq it performs will take us out of NMI context.
371 diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
372 index 5314d7b8e5ad..d8468ba24be0 100644
373 --- a/arch/x86/entry/entry_64_compat.S
374 +++ b/arch/x86/entry/entry_64_compat.S
375 @@ -293,7 +293,6 @@ ENTRY(entry_INT80_compat)
376 /*
377 * Interrupts are off on entry.
378 */
379 - PARAVIRT_ADJUST_EXCEPTION_FRAME
380 ASM_CLAC /* Do this early to minimize exposure */
381 SWAPGS
382
383 diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S
384 index 3a3b6a211584..dae2cc33afb5 100644
385 --- a/arch/x86/xen/xen-asm_64.S
386 +++ b/arch/x86/xen/xen-asm_64.S
387 @@ -16,11 +16,42 @@
388
389 #include <linux/linkage.h>
390
391 -ENTRY(xen_adjust_exception_frame)
392 - mov 8+0(%rsp), %rcx
393 - mov 8+8(%rsp), %r11
394 - ret $16
395 -ENDPROC(xen_adjust_exception_frame)
396 +.macro xen_pv_trap name
397 +ENTRY(xen_\name)
398 + pop %rcx
399 + pop %r11
400 + jmp \name
401 +END(xen_\name)
402 +.endm
403 +
404 +xen_pv_trap divide_error
405 +xen_pv_trap debug
406 +xen_pv_trap xendebug
407 +xen_pv_trap int3
408 +xen_pv_trap xenint3
409 +xen_pv_trap nmi
410 +xen_pv_trap overflow
411 +xen_pv_trap bounds
412 +xen_pv_trap invalid_op
413 +xen_pv_trap device_not_available
414 +xen_pv_trap double_fault
415 +xen_pv_trap coprocessor_segment_overrun
416 +xen_pv_trap invalid_TSS
417 +xen_pv_trap segment_not_present
418 +xen_pv_trap stack_segment
419 +xen_pv_trap general_protection
420 +xen_pv_trap page_fault
421 +xen_pv_trap spurious_interrupt_bug
422 +xen_pv_trap coprocessor_error
423 +xen_pv_trap alignment_check
424 +#ifdef CONFIG_X86_MCE
425 +xen_pv_trap machine_check
426 +#endif /* CONFIG_X86_MCE */
427 +xen_pv_trap simd_coprocessor_error
428 +#ifdef CONFIG_IA32_EMULATION
429 +xen_pv_trap entry_INT80_compat
430 +#endif
431 +xen_pv_trap hypervisor_callback
432
433 hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
434 /*
435 --
436 2.14.2
437