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 <aarcange@redhat.com>
Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: John Haxby <john.haxby@oracle.com>
Signed-off-by: Kirtikar Kashyap <kirtikar.kashyap@oracle.com>
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
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)
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:
movq $-1,%rsi
call do_nmi
+ RESTORE_IBRS_CLOBBER save_reg=%r13d
+
testl %ebx,%ebx /* swapgs needed? */
jnz nmi_restore
nmi_swapgs: