0088-x86-entry-64-Move-SWAPGS-into-the-common-IRET-to-use.patch 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. From 271bc7d0577bef9f344187eb45ba8682eed242f9 Mon Sep 17 00:00:00 2001
  2. From: Andy Lutomirski <[email protected]>
  3. Date: Thu, 2 Nov 2017 00:59:00 -0700
  4. Subject: [PATCH 088/242] x86/entry/64: Move SWAPGS into the common
  5. IRET-to-usermode path
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. CVE-2017-5754
  10. All of the code paths that ended up doing IRET to usermode did
  11. SWAPGS immediately beforehand. Move the SWAPGS into the common
  12. code.
  13. Signed-off-by: Andy Lutomirski <[email protected]>
  14. Cc: Borislav Petkov <[email protected]>
  15. Cc: Brian Gerst <[email protected]>
  16. Cc: Dave Hansen <[email protected]>
  17. Cc: Linus Torvalds <[email protected]>
  18. Cc: Peter Zijlstra <[email protected]>
  19. Cc: Thomas Gleixner <[email protected]>
  20. Link: http://lkml.kernel.org/r/27fd6f45b7cd640de38fb9066fd0349bcd11f8e1.1509609304.git.luto@kernel.org
  21. Signed-off-by: Ingo Molnar <[email protected]>
  22. (cherry picked from commit 8a055d7f411d41755ce30db5bb65b154777c4b78)
  23. Signed-off-by: Andy Whitcroft <[email protected]>
  24. Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
  25. (cherry picked from commit 62a85594f9be3baeb2495089f1c2980bc497d03b)
  26. Signed-off-by: Fabian Grünbichler <[email protected]>
  27. ---
  28. arch/x86/entry/entry_64.S | 32 ++++++++++++++------------------
  29. arch/x86/entry/entry_64_compat.S | 3 +--
  30. 2 files changed, 15 insertions(+), 20 deletions(-)
  31. diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
  32. index e546441fbec3..7c8258e3ad2d 100644
  33. --- a/arch/x86/entry/entry_64.S
  34. +++ b/arch/x86/entry/entry_64.S
  35. @@ -249,12 +249,14 @@ return_from_SYSCALL_64:
  36. /*
  37. * Try to use SYSRET instead of IRET if we're returning to
  38. - * a completely clean 64-bit userspace context.
  39. + * a completely clean 64-bit userspace context. If we're not,
  40. + * go to the slow exit path.
  41. */
  42. movq RCX(%rsp), %rcx
  43. movq RIP(%rsp), %r11
  44. - cmpq %rcx, %r11 /* RCX == RIP */
  45. - jne opportunistic_sysret_failed
  46. +
  47. + cmpq %rcx, %r11 /* SYSRET requires RCX == RIP */
  48. + jne swapgs_restore_regs_and_return_to_usermode
  49. /*
  50. * On Intel CPUs, SYSRET with non-canonical RCX/RIP will #GP
  51. @@ -272,14 +274,14 @@ return_from_SYSCALL_64:
  52. /* If this changed %rcx, it was not canonical */
  53. cmpq %rcx, %r11
  54. - jne opportunistic_sysret_failed
  55. + jne swapgs_restore_regs_and_return_to_usermode
  56. cmpq $__USER_CS, CS(%rsp) /* CS must match SYSRET */
  57. - jne opportunistic_sysret_failed
  58. + jne swapgs_restore_regs_and_return_to_usermode
  59. movq R11(%rsp), %r11
  60. cmpq %r11, EFLAGS(%rsp) /* R11 == RFLAGS */
  61. - jne opportunistic_sysret_failed
  62. + jne swapgs_restore_regs_and_return_to_usermode
  63. /*
  64. * SYSCALL clears RF when it saves RFLAGS in R11 and SYSRET cannot
  65. @@ -300,12 +302,12 @@ return_from_SYSCALL_64:
  66. * would never get past 'stuck_here'.
  67. */
  68. testq $(X86_EFLAGS_RF|X86_EFLAGS_TF), %r11
  69. - jnz opportunistic_sysret_failed
  70. + jnz swapgs_restore_regs_and_return_to_usermode
  71. /* nothing to check for RSP */
  72. cmpq $__USER_DS, SS(%rsp) /* SS must match SYSRET */
  73. - jne opportunistic_sysret_failed
  74. + jne swapgs_restore_regs_and_return_to_usermode
  75. /*
  76. * We win! This label is here just for ease of understanding
  77. @@ -318,10 +320,6 @@ syscall_return_via_sysret:
  78. movq RSP(%rsp), %rsp
  79. UNWIND_HINT_EMPTY
  80. USERGS_SYSRET64
  81. -
  82. -opportunistic_sysret_failed:
  83. - SWAPGS
  84. - jmp restore_regs_and_return_to_usermode
  85. END(entry_SYSCALL_64)
  86. ENTRY(stub_ptregs_64)
  87. @@ -422,8 +420,7 @@ ENTRY(ret_from_fork)
  88. movq %rsp, %rdi
  89. call syscall_return_slowpath /* returns with IRQs disabled */
  90. TRACE_IRQS_ON /* user mode is traced as IRQS on */
  91. - SWAPGS
  92. - jmp restore_regs_and_return_to_usermode
  93. + jmp swapgs_restore_regs_and_return_to_usermode
  94. 1:
  95. /* kernel thread */
  96. @@ -611,9 +608,8 @@ GLOBAL(retint_user)
  97. mov %rsp,%rdi
  98. call prepare_exit_to_usermode
  99. TRACE_IRQS_IRETQ
  100. - SWAPGS
  101. -GLOBAL(restore_regs_and_return_to_usermode)
  102. +GLOBAL(swapgs_restore_regs_and_return_to_usermode)
  103. #ifdef CONFIG_DEBUG_ENTRY
  104. /* Assert that pt_regs indicates user mode. */
  105. testl $3, CS(%rsp)
  106. @@ -621,6 +617,7 @@ GLOBAL(restore_regs_and_return_to_usermode)
  107. ud2
  108. 1:
  109. #endif
  110. + SWAPGS
  111. RESTORE_EXTRA_REGS
  112. RESTORE_C_REGS
  113. REMOVE_PT_GPREGS_FROM_STACK 8
  114. @@ -1355,8 +1352,7 @@ ENTRY(nmi)
  115. * Return back to user mode. We must *not* do the normal exit
  116. * work, because we don't want to enable interrupts.
  117. */
  118. - SWAPGS
  119. - jmp restore_regs_and_return_to_usermode
  120. + jmp swapgs_restore_regs_and_return_to_usermode
  121. .Lnmi_from_kernel:
  122. /*
  123. diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
  124. index 2b3a88feaa2b..be745b7a3e3e 100644
  125. --- a/arch/x86/entry/entry_64_compat.S
  126. +++ b/arch/x86/entry/entry_64_compat.S
  127. @@ -336,8 +336,7 @@ ENTRY(entry_INT80_compat)
  128. /* Go back to user mode. */
  129. TRACE_IRQS_ON
  130. - SWAPGS
  131. - jmp restore_regs_and_return_to_usermode
  132. + jmp swapgs_restore_regs_and_return_to_usermode
  133. END(entry_INT80_compat)
  134. ALIGN
  135. --
  136. 2.14.2