Commit 4e4050bd authored by Tim Chen's avatar Tim Chen Committed by Khalid Elmously

x86/enter: Use IBRS on syscall and interrupts

CVE-2017-5715 (Spectre v2 Intel)

Set IBRS upon kernel entrance via syscall and interrupts. Clear it upon exit.
Signed-off-by: default avatarTim Chen <tim.c.chen@linux.intel.com>
Signed-off-by: default avatarAndy Whitcroft <apw@canonical.com>
(backported from commit bb6c1a01e82fb0eb14d1229fd71a99ed285d330d)
Signed-off-by: default avatarAndy Whitcroft <apw@canonical.com>
Acked-by: default avatarColin Ian King <colin.king@canonical.com>
Acked-by: default avatarKamal Mostafa <kamal@canonical.com>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
parent b75d4153
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <asm/pgtable_types.h> #include <asm/pgtable_types.h>
#include <asm/kaiser.h> #include <asm/kaiser.h>
#include <asm/nospec-branch.h> #include <asm/nospec-branch.h>
#include <asm/spec_ctrl.h>
#include <linux/err.h> #include <linux/err.h>
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */ /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
...@@ -174,6 +175,8 @@ GLOBAL(entry_SYSCALL_64_after_swapgs) ...@@ -174,6 +175,8 @@ GLOBAL(entry_SYSCALL_64_after_swapgs)
pushq %r11 /* pt_regs->r11 */ pushq %r11 /* pt_regs->r11 */
sub $(6*8), %rsp /* pt_regs->bp, bx, r12-15 not saved */ sub $(6*8), %rsp /* pt_regs->bp, bx, r12-15 not saved */
ENABLE_IBRS
testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
jnz tracesys jnz tracesys
entry_SYSCALL_64_fastpath: entry_SYSCALL_64_fastpath:
...@@ -219,6 +222,9 @@ entry_SYSCALL_64_fastpath: ...@@ -219,6 +222,9 @@ entry_SYSCALL_64_fastpath:
movq RIP(%rsp), %rcx movq RIP(%rsp), %rcx
movq EFLAGS(%rsp), %r11 movq EFLAGS(%rsp), %r11
RESTORE_C_REGS_EXCEPT_RCX_R11 RESTORE_C_REGS_EXCEPT_RCX_R11
DISABLE_IBRS
/* /*
* This opens a window where we have a user CR3, but are * This opens a window where we have a user CR3, but are
* running in the kernel. This makes using the CS * running in the kernel. This makes using the CS
...@@ -367,6 +373,8 @@ GLOBAL(int_ret_from_sys_call) ...@@ -367,6 +373,8 @@ GLOBAL(int_ret_from_sys_call)
* perf profiles. Nothing jumps here. * perf profiles. Nothing jumps here.
*/ */
syscall_return_via_sysret: syscall_return_via_sysret:
DISABLE_IBRS
/* rcx and r11 are already restored (see code above) */ /* rcx and r11 are already restored (see code above) */
RESTORE_C_REGS_EXCEPT_RCX_R11 RESTORE_C_REGS_EXCEPT_RCX_R11
/* /*
...@@ -381,6 +389,7 @@ syscall_return_via_sysret: ...@@ -381,6 +389,7 @@ syscall_return_via_sysret:
USERGS_SYSRET64 USERGS_SYSRET64
opportunistic_sysret_failed: opportunistic_sysret_failed:
/* XXX: might we need a DISABLE_IBRS */
/* /*
* This opens a window where we have a user CR3, but are * This opens a window where we have a user CR3, but are
* running in the kernel. This makes using the CS * running in the kernel. This makes using the CS
...@@ -549,6 +558,8 @@ END(irq_entries_start) ...@@ -549,6 +558,8 @@ END(irq_entries_start)
SWAPGS SWAPGS
SWITCH_KERNEL_CR3 SWITCH_KERNEL_CR3
ENABLE_IBRS
/* /*
* We need to tell lockdep that IRQs are off. We can't do this until * We need to tell lockdep that IRQs are off. We can't do this until
* we fix gsbase, and we should do it before enter_from_user_mode * we fix gsbase, and we should do it before enter_from_user_mode
...@@ -607,6 +618,7 @@ GLOBAL(retint_user) ...@@ -607,6 +618,7 @@ GLOBAL(retint_user)
mov %rsp,%rdi mov %rsp,%rdi
call prepare_exit_to_usermode call prepare_exit_to_usermode
TRACE_IRQS_IRETQ TRACE_IRQS_IRETQ
DISABLE_IBRS
SWITCH_USER_CR3 SWITCH_USER_CR3
SWAPGS SWAPGS
jmp restore_regs_and_iret jmp restore_regs_and_iret
...@@ -1073,6 +1085,8 @@ ENTRY(paranoid_entry) ...@@ -1073,6 +1085,8 @@ ENTRY(paranoid_entry)
movq %rax, %cr3 movq %rax, %cr3
2: 2:
#endif #endif
ENABLE_IBRS_CLOBBER
ret ret
END(paranoid_entry) END(paranoid_entry)
...@@ -1099,6 +1113,7 @@ ENTRY(paranoid_exit) ...@@ -1099,6 +1113,7 @@ ENTRY(paranoid_exit)
/* No ALTERNATIVE for X86_FEATURE_KAISER: paranoid_entry sets %ebx */ /* No ALTERNATIVE for X86_FEATURE_KAISER: paranoid_entry sets %ebx */
testl $2, %ebx /* SWITCH_USER_CR3 needed? */ testl $2, %ebx /* SWITCH_USER_CR3 needed? */
jz paranoid_exit_no_switch jz paranoid_exit_no_switch
DISABLE_IBRS
SWITCH_USER_CR3 SWITCH_USER_CR3
paranoid_exit_no_switch: paranoid_exit_no_switch:
#endif #endif
...@@ -1138,6 +1153,8 @@ ENTRY(error_entry) ...@@ -1138,6 +1153,8 @@ ENTRY(error_entry)
*/ */
SWAPGS SWAPGS
ENABLE_IBRS
.Lerror_entry_from_usermode_after_swapgs: .Lerror_entry_from_usermode_after_swapgs:
/* /*
* We need to tell lockdep that IRQs are off. We can't do this until * We need to tell lockdep that IRQs are off. We can't do this until
...@@ -1188,6 +1205,7 @@ ENTRY(error_entry) ...@@ -1188,6 +1205,7 @@ ENTRY(error_entry)
* We came from an IRET to user mode, so we have user gsbase. * We came from an IRET to user mode, so we have user gsbase.
* Switch to kernel gsbase: * Switch to kernel gsbase:
*/ */
ENABLE_IBRS_CLOBBER
SWAPGS SWAPGS
/* /*
...@@ -1338,6 +1356,7 @@ ENTRY(nmi) ...@@ -1338,6 +1356,7 @@ ENTRY(nmi)
movq %rax, %cr3 movq %rax, %cr3
2: 2:
#endif #endif
ENABLE_IBRS
call do_nmi call do_nmi
#ifdef CONFIG_KAISER #ifdef CONFIG_KAISER
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <asm/smap.h> #include <asm/smap.h>
#include <asm/pgtable_types.h> #include <asm/pgtable_types.h>
#include <asm/kaiser.h> #include <asm/kaiser.h>
#include <asm/spec_ctrl.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -99,6 +100,8 @@ ENTRY(entry_SYSENTER_compat) ...@@ -99,6 +100,8 @@ ENTRY(entry_SYSENTER_compat)
pushq %r8 /* pt_regs->r15 = 0 */ pushq %r8 /* pt_regs->r15 = 0 */
cld cld
ENABLE_IBRS
/* /*
* Sysenter doesn't filter flags, so we need to clear NT * Sysenter doesn't filter flags, so we need to clear NT
* ourselves. To save a few cycles, we can check whether * ourselves. To save a few cycles, we can check whether
...@@ -197,6 +200,8 @@ ENTRY(entry_SYSCALL_compat) ...@@ -197,6 +200,8 @@ ENTRY(entry_SYSCALL_compat)
pushq %r8 /* pt_regs->r14 = 0 */ pushq %r8 /* pt_regs->r14 = 0 */
pushq %r8 /* pt_regs->r15 = 0 */ pushq %r8 /* pt_regs->r15 = 0 */
ENABLE_IBRS
/* /*
* User mode is traced as though IRQs are on, and SYSENTER * User mode is traced as though IRQs are on, and SYSENTER
* turned them off. * turned them off.
...@@ -212,6 +217,7 @@ ENTRY(entry_SYSCALL_compat) ...@@ -212,6 +217,7 @@ ENTRY(entry_SYSCALL_compat)
/* Opportunistic SYSRET */ /* Opportunistic SYSRET */
sysret32_from_system_call: sysret32_from_system_call:
TRACE_IRQS_ON /* User mode traces as IRQs on. */ TRACE_IRQS_ON /* User mode traces as IRQs on. */
DISABLE_IBRS
SWITCH_USER_CR3 SWITCH_USER_CR3
movq RBX(%rsp), %rbx /* pt_regs->rbx */ movq RBX(%rsp), %rbx /* pt_regs->rbx */
movq RBP(%rsp), %rbp /* pt_regs->rbp */ movq RBP(%rsp), %rbp /* pt_regs->rbp */
...@@ -305,6 +311,8 @@ ENTRY(entry_INT80_compat) ...@@ -305,6 +311,8 @@ ENTRY(entry_INT80_compat)
pushq %r15 /* pt_regs->r15 */ pushq %r15 /* pt_regs->r15 */
cld cld
ENABLE_IBRS
/* /*
* User mode is traced as though IRQs are on, and the interrupt * User mode is traced as though IRQs are on, and the interrupt
* gate turned them off. * gate turned them off.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment