From: Alejandro Jimenez Date: Wed, 20 Mar 2019 15:00:49 +0000 (-0400) Subject: x86/speculation: Keep enhanced IBRS on when prctl is used for SSBD control X-Git-Tag: v4.1.12-124.31.3~162 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=5a415bc0a3b989c3ada14a68c697515738694633;p=users%2Fjedix%2Flinux-maple.git x86/speculation: Keep enhanced IBRS on when prctl is used for SSBD control When using the prctl system call to enable/disable SSBD mitigation for a specific thread, it is necessary to update the SPEC_CTRL MSR on the CPU running it. The value used as the base for the msr that will be written is x86_spec_ctrl_base, which does not have the IBRS bit set. The relevant SSBD bits are OR'd to this value before it is written to the MSR, but the IBRS bit will remain unset. As a result, the thread that requested the SSBD protection will run without IBRS enabled, and when it is context switched out, IBRS will not be turned back on again. This is not a problem in processors that use basic IBRS since the bit is constantly toggled on kernel entry, but with enhanced IBRS this is not necessary and therefore the bit remains unset. Fix it by adding a check to detect when enhanced IBRS is in use, and add the bit to the msr value that will be used as the baseline. Orabug: 29526401 Signed-off-by: Alejandro Jimenez Reviewed-by: Boris Ostrovsky Signed-off-by: Brian Maly --- diff --git a/arch/x86/include/asm/spec_ctrl.h b/arch/x86/include/asm/spec_ctrl.h index ecfc95139560..09e8b761a74d 100644 --- a/arch/x86/include/asm/spec_ctrl.h +++ b/arch/x86/include/asm/spec_ctrl.h @@ -308,6 +308,16 @@ static inline int check_basic_ibrs_inuse(void) return 0; } +static inline int check_enhanced_ibrs_inuse(void) +{ + if (use_ibrs & SPEC_CTRL_ENHCD_IBRS_INUSE) + return 1; + + /* rmb to prevent wrong speculation for security */ + rmb(); + return 0; +} + static inline int check_ibrs_inuse(void) { if (use_ibrs & (SPEC_CTRL_BASIC_IBRS_INUSE | diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index c6d19f35bb57..0d4f2a4c466d 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -350,7 +350,9 @@ static __always_inline void amd_set_ssb_virt_state(unsigned long tifn) static __always_inline void intel_set_ssb_state(unsigned long tifn) { - u64 msr = x86_spec_ctrl_base | ssbd_tif_to_spec_ctrl(tifn); + u64 msr = x86_spec_ctrl_base | (check_enhanced_ibrs_inuse() ? + SPEC_CTRL_FEATURE_ENABLE_IBRS : 0); + msr |= ssbd_tif_to_spec_ctrl(tifn); this_cpu_write(x86_spec_ctrl_restore, msr); wrmsrl(MSR_IA32_SPEC_CTRL, msr);