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 <alejandro.j.jimenez@oracle.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
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 |
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);