From 42c22a28024ee8f6695836ae38761bb46b46b73c Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Thu, 14 Dec 2017 16:04:25 -0800 Subject: [PATCH] x86/spec_ctrl: save IBRS MSR value in paranoid_entry If the NMI runs while entering kernel between SWAPGS and IBRS_ENABLE everything is fine, paranoid_entry would have unconditionally set IBRS bit 0 and when exiting the NMI it would have cleared bit 0 like if it was returning to userland. IBRS_ENABLE would have then enabled bit 0 again. If NMI instead runs when exiting kernel between IBRS_DISABLE and SWAPGS, the NMI would have turned on IBRS bit 0 and then it would have left enabled when exiting the NMI. IBRS bit 0 would then be left enabled in userland until the next enter kernel. That is a minor inefficiency only, but we can eliminate it by saving the MSR when entering the NMI in save_paranoid and restoring it when exiting the NMI. Orabug: 27344012 CVE: CVE-2017-5715 Signed-off-by: Andrea Arcangeli Signed-off-by: Tim Chen Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: John Haxby Signed-off-by: Kirtikar Kashyap --- arch/x86/include/asm/spec_ctrl.h | 34 ++++++++++++++++++++++++++++++++ arch/x86/kernel/entry_64.S | 5 ++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/spec_ctrl.h b/arch/x86/include/asm/spec_ctrl.h index 1d313ff9799b..712f12deea32 100644 --- a/arch/x86/include/asm/spec_ctrl.h +++ b/arch/x86/include/asm/spec_ctrl.h @@ -65,6 +65,40 @@ ALTERNATIVE "", __stringify(__ASM_ENABLE_IBRS), X86_FEATURE_SPEC_CTRL 11: .endm +.macro ENABLE_IBRS_SAVE_AND_CLOBBER save_reg:req + testl $1, use_ibrs + jz 12f + + movl $MSR_IA32_SPEC_CTRL, %ecx + rdmsr + movl %eax, \save_reg + + movl $0, %edx + movl $FEATURE_ENABLE_IBRS, %eax + wrmsr + jmp 22f +12: + lfence +22: +.endm + +.macro RESTORE_IBRS_CLOBBER save_reg:req + testl $1, use_ibrs + jz 13f + + cmpl $FEATURE_ENABLE_IBRS, \save_reg + je 13f + + movl $MSR_IA32_SPEC_CTRL, %ecx + movl $0, %edx + movl \save_reg, %eax + wrmsr + jmp 23f +13: + lfence +23: +.endm + .macro DISABLE_IBRS ALTERNATIVE "", __stringify(__ASM_DISABLE_IBRS), X86_FEATURE_SPEC_CTRL .endm diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 82148ae50eb1..157c53c82031 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1437,7 +1437,7 @@ ENTRY(paranoid_entry) js 1f /* negative -> in kernel */ SWAPGS xorl %ebx,%ebx -1: ENABLE_IBRS_CLOBBER +1: ENABLE_IBRS_SAVE_AND_CLOBBER save_reg=%r13d ret CFI_ENDPROC END(paranoid_entry) @@ -1460,6 +1460,7 @@ ENTRY(paranoid_exit) testl %ebx,%ebx /* swapgs needed? */ jnz paranoid_exit_no_swapgs TRACE_IRQS_IRETQ + RESTORE_IBRS_CLOBBER save_reg=%r13d SWAPGS_UNSAFE_STACK jmp paranoid_exit_restore paranoid_exit_no_swapgs: @@ -1864,6 +1865,8 @@ end_repeat_nmi: movq $-1,%rsi call do_nmi + RESTORE_IBRS_CLOBBER save_reg=%r13d + testl %ebx,%ebx /* swapgs needed? */ jnz nmi_restore nmi_swapgs: -- 2.50.1