x86/speculation: Disable RRSBA behavior
commit 4ad3278df6
upstream.
Some Intel processors may use alternate predictors for RETs on
RSB-underflow. This condition may be vulnerable to Branch History
Injection (BHI) and intramode-BTI.
Kernel earlier added spectre_v2 mitigation modes (eIBRS+Retpolines,
eIBRS+LFENCE, Retpolines) which protect indirect CALLs and JMPs against
such attacks. However, on RSB-underflow, RET target prediction may
fallback to alternate predictors. As a result, RET's predicted target
may get influenced by branch history.
A new MSR_IA32_SPEC_CTRL bit (RRSBA_DIS_S) controls this fallback
behavior when in kernel mode. When set, RETs will not take predictions
from alternate predictors, hence mitigating RETs as well. Support for
this is enumerated by CPUID.7.2.EDX[RRSBA_CTRL] (bit2).
For spectre v2 mitigation, when a user selects a mitigation that
protects indirect CALLs and JMPs against BHI and intramode-BTI, set
RRSBA_DIS_S also to protect RETs for RSB-underflow case.
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
[cascardo: no X86_FEATURE_INTEL_PPIN]
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
db0128b824
Коммит
73ad137d11
|
@ -295,7 +295,7 @@
|
||||||
#define X86_FEATURE_SGX1 (11*32+ 8) /* "" Basic SGX */
|
#define X86_FEATURE_SGX1 (11*32+ 8) /* "" Basic SGX */
|
||||||
#define X86_FEATURE_SGX2 (11*32+ 9) /* "" SGX Enclave Dynamic Memory Management (EDMM) */
|
#define X86_FEATURE_SGX2 (11*32+ 9) /* "" SGX Enclave Dynamic Memory Management (EDMM) */
|
||||||
#define X86_FEATURE_ENTRY_IBPB (11*32+10) /* "" Issue an IBPB on kernel entry */
|
#define X86_FEATURE_ENTRY_IBPB (11*32+10) /* "" Issue an IBPB on kernel entry */
|
||||||
/* FREE! (11*32+11) */
|
#define X86_FEATURE_RRSBA_CTRL (11*32+11) /* "" RET prediction control */
|
||||||
#define X86_FEATURE_RETPOLINE (11*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */
|
#define X86_FEATURE_RETPOLINE (11*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */
|
||||||
#define X86_FEATURE_RETPOLINE_LFENCE (11*32+13) /* "" Use LFENCE for Spectre variant 2 */
|
#define X86_FEATURE_RETPOLINE_LFENCE (11*32+13) /* "" Use LFENCE for Spectre variant 2 */
|
||||||
#define X86_FEATURE_RETHUNK (11*32+14) /* "" Use REturn THUNK */
|
#define X86_FEATURE_RETHUNK (11*32+14) /* "" Use REturn THUNK */
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
#define SPEC_CTRL_STIBP BIT(SPEC_CTRL_STIBP_SHIFT) /* STIBP mask */
|
#define SPEC_CTRL_STIBP BIT(SPEC_CTRL_STIBP_SHIFT) /* STIBP mask */
|
||||||
#define SPEC_CTRL_SSBD_SHIFT 2 /* Speculative Store Bypass Disable bit */
|
#define SPEC_CTRL_SSBD_SHIFT 2 /* Speculative Store Bypass Disable bit */
|
||||||
#define SPEC_CTRL_SSBD BIT(SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */
|
#define SPEC_CTRL_SSBD BIT(SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */
|
||||||
|
#define SPEC_CTRL_RRSBA_DIS_S_SHIFT 6 /* Disable RRSBA behavior */
|
||||||
|
#define SPEC_CTRL_RRSBA_DIS_S BIT(SPEC_CTRL_RRSBA_DIS_S_SHIFT)
|
||||||
|
|
||||||
#define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */
|
#define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */
|
||||||
#define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */
|
#define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */
|
||||||
|
@ -139,6 +141,13 @@
|
||||||
* bit available to control VERW
|
* bit available to control VERW
|
||||||
* behavior.
|
* behavior.
|
||||||
*/
|
*/
|
||||||
|
#define ARCH_CAP_RRSBA BIT(19) /*
|
||||||
|
* Indicates RET may use predictors
|
||||||
|
* other than the RSB. With eIBRS
|
||||||
|
* enabled predictions in kernel mode
|
||||||
|
* are restricted to targets in
|
||||||
|
* kernel.
|
||||||
|
*/
|
||||||
|
|
||||||
#define MSR_IA32_FLUSH_CMD 0x0000010b
|
#define MSR_IA32_FLUSH_CMD 0x0000010b
|
||||||
#define L1D_FLUSH BIT(0) /*
|
#define L1D_FLUSH BIT(0) /*
|
||||||
|
|
|
@ -1311,6 +1311,22 @@ static enum spectre_v2_mitigation __init spectre_v2_select_retpoline(void)
|
||||||
return SPECTRE_V2_RETPOLINE;
|
return SPECTRE_V2_RETPOLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable in-kernel use of non-RSB RET predictors */
|
||||||
|
static void __init spec_ctrl_disable_kernel_rrsba(void)
|
||||||
|
{
|
||||||
|
u64 ia32_cap;
|
||||||
|
|
||||||
|
if (!boot_cpu_has(X86_FEATURE_RRSBA_CTRL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ia32_cap = x86_read_arch_cap_msr();
|
||||||
|
|
||||||
|
if (ia32_cap & ARCH_CAP_RRSBA) {
|
||||||
|
x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S;
|
||||||
|
write_spec_ctrl_current(x86_spec_ctrl_base, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void __init spectre_v2_select_mitigation(void)
|
static void __init spectre_v2_select_mitigation(void)
|
||||||
{
|
{
|
||||||
enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
|
enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
|
||||||
|
@ -1405,6 +1421,16 @@ static void __init spectre_v2_select_mitigation(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable alternate RSB predictions in kernel when indirect CALLs and
|
||||||
|
* JMPs gets protection against BHI and Intramode-BTI, but RET
|
||||||
|
* prediction from a non-RSB predictor is still a risk.
|
||||||
|
*/
|
||||||
|
if (mode == SPECTRE_V2_EIBRS_LFENCE ||
|
||||||
|
mode == SPECTRE_V2_EIBRS_RETPOLINE ||
|
||||||
|
mode == SPECTRE_V2_RETPOLINE)
|
||||||
|
spec_ctrl_disable_kernel_rrsba();
|
||||||
|
|
||||||
spectre_v2_enabled = mode;
|
spectre_v2_enabled = mode;
|
||||||
pr_info("%s\n", spectre_v2_strings[mode]);
|
pr_info("%s\n", spectre_v2_strings[mode]);
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ struct cpuid_bit {
|
||||||
static const struct cpuid_bit cpuid_bits[] = {
|
static const struct cpuid_bit cpuid_bits[] = {
|
||||||
{ X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 },
|
{ X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 },
|
||||||
{ X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 },
|
{ X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 },
|
||||||
|
{ X86_FEATURE_RRSBA_CTRL, CPUID_EDX, 2, 0x00000007, 2 },
|
||||||
{ X86_FEATURE_CQM_LLC, CPUID_EDX, 1, 0x0000000f, 0 },
|
{ X86_FEATURE_CQM_LLC, CPUID_EDX, 1, 0x0000000f, 0 },
|
||||||
{ X86_FEATURE_CQM_OCCUP_LLC, CPUID_EDX, 0, 0x0000000f, 1 },
|
{ X86_FEATURE_CQM_OCCUP_LLC, CPUID_EDX, 0, 0x0000000f, 1 },
|
||||||
{ X86_FEATURE_CQM_MBM_TOTAL, CPUID_EDX, 1, 0x0000000f, 1 },
|
{ X86_FEATURE_CQM_MBM_TOTAL, CPUID_EDX, 1, 0x0000000f, 1 },
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
#define SPEC_CTRL_STIBP BIT(SPEC_CTRL_STIBP_SHIFT) /* STIBP mask */
|
#define SPEC_CTRL_STIBP BIT(SPEC_CTRL_STIBP_SHIFT) /* STIBP mask */
|
||||||
#define SPEC_CTRL_SSBD_SHIFT 2 /* Speculative Store Bypass Disable bit */
|
#define SPEC_CTRL_SSBD_SHIFT 2 /* Speculative Store Bypass Disable bit */
|
||||||
#define SPEC_CTRL_SSBD BIT(SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */
|
#define SPEC_CTRL_SSBD BIT(SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */
|
||||||
|
#define SPEC_CTRL_RRSBA_DIS_S_SHIFT 6 /* Disable RRSBA behavior */
|
||||||
|
#define SPEC_CTRL_RRSBA_DIS_S BIT(SPEC_CTRL_RRSBA_DIS_S_SHIFT)
|
||||||
|
|
||||||
#define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */
|
#define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */
|
||||||
#define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */
|
#define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */
|
||||||
|
@ -138,6 +140,13 @@
|
||||||
* bit available to control VERW
|
* bit available to control VERW
|
||||||
* behavior.
|
* behavior.
|
||||||
*/
|
*/
|
||||||
|
#define ARCH_CAP_RRSBA BIT(19) /*
|
||||||
|
* Indicates RET may use predictors
|
||||||
|
* other than the RSB. With eIBRS
|
||||||
|
* enabled predictions in kernel mode
|
||||||
|
* are restricted to targets in
|
||||||
|
* kernel.
|
||||||
|
*/
|
||||||
|
|
||||||
#define MSR_IA32_FLUSH_CMD 0x0000010b
|
#define MSR_IA32_FLUSH_CMD 0x0000010b
|
||||||
#define L1D_FLUSH BIT(0) /*
|
#define L1D_FLUSH BIT(0) /*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче