0029-x86-xen-Get-rid-of-paravirt-op-adjust_exception_fram.patch 15 KB

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