mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
x86/bugs: Restructure spectre_v2 mitigation
Restructure spectre_v2 to use select/update/apply functions to create consistent vulnerability handling. The spectre_v2 mitigation may be updated based on the selected retbleed mitigation. Signed-off-by: David Kaplan <david.kaplan@amd.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org> Link: https://lore.kernel.org/20250418161721.1855190-14-david.kaplan@amd.com
This commit is contained in:
parent
efe313827c
commit
480e803dac
@ -56,6 +56,8 @@
|
||||
static void __init spectre_v1_select_mitigation(void);
|
||||
static void __init spectre_v1_apply_mitigation(void);
|
||||
static void __init spectre_v2_select_mitigation(void);
|
||||
static void __init spectre_v2_update_mitigation(void);
|
||||
static void __init spectre_v2_apply_mitigation(void);
|
||||
static void __init retbleed_select_mitigation(void);
|
||||
static void __init retbleed_update_mitigation(void);
|
||||
static void __init retbleed_apply_mitigation(void);
|
||||
@ -217,6 +219,12 @@ void __init cpu_select_mitigations(void)
|
||||
* After mitigations are selected, some may need to update their
|
||||
* choices.
|
||||
*/
|
||||
spectre_v2_update_mitigation();
|
||||
/*
|
||||
* retbleed_update_mitigation() relies on the state set by
|
||||
* spectre_v2_update_mitigation(); specifically it wants to know about
|
||||
* spectre_v2=ibrs.
|
||||
*/
|
||||
retbleed_update_mitigation();
|
||||
|
||||
/*
|
||||
@ -232,6 +240,7 @@ void __init cpu_select_mitigations(void)
|
||||
bhi_update_mitigation();
|
||||
|
||||
spectre_v1_apply_mitigation();
|
||||
spectre_v2_apply_mitigation();
|
||||
retbleed_apply_mitigation();
|
||||
spectre_v2_user_apply_mitigation();
|
||||
mds_apply_mitigation();
|
||||
@ -1878,75 +1887,80 @@ static void __init bhi_apply_mitigation(void)
|
||||
|
||||
static void __init spectre_v2_select_mitigation(void)
|
||||
{
|
||||
enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
|
||||
enum spectre_v2_mitigation mode = SPECTRE_V2_NONE;
|
||||
spectre_v2_cmd = spectre_v2_parse_cmdline();
|
||||
|
||||
/*
|
||||
* If the CPU is not affected and the command line mode is NONE or AUTO
|
||||
* then nothing to do.
|
||||
*/
|
||||
if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2) &&
|
||||
(cmd == SPECTRE_V2_CMD_NONE || cmd == SPECTRE_V2_CMD_AUTO))
|
||||
(spectre_v2_cmd == SPECTRE_V2_CMD_NONE || spectre_v2_cmd == SPECTRE_V2_CMD_AUTO))
|
||||
return;
|
||||
|
||||
switch (cmd) {
|
||||
switch (spectre_v2_cmd) {
|
||||
case SPECTRE_V2_CMD_NONE:
|
||||
return;
|
||||
|
||||
case SPECTRE_V2_CMD_FORCE:
|
||||
case SPECTRE_V2_CMD_AUTO:
|
||||
if (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED)) {
|
||||
mode = SPECTRE_V2_EIBRS;
|
||||
spectre_v2_enabled = SPECTRE_V2_EIBRS;
|
||||
break;
|
||||
}
|
||||
|
||||
spectre_v2_enabled = spectre_v2_select_retpoline();
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_RETPOLINE_LFENCE:
|
||||
pr_err(SPECTRE_V2_LFENCE_MSG);
|
||||
spectre_v2_enabled = SPECTRE_V2_LFENCE;
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_RETPOLINE_GENERIC:
|
||||
spectre_v2_enabled = SPECTRE_V2_RETPOLINE;
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_RETPOLINE:
|
||||
spectre_v2_enabled = spectre_v2_select_retpoline();
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_IBRS:
|
||||
spectre_v2_enabled = SPECTRE_V2_IBRS;
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_EIBRS:
|
||||
spectre_v2_enabled = SPECTRE_V2_EIBRS;
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_EIBRS_LFENCE:
|
||||
spectre_v2_enabled = SPECTRE_V2_EIBRS_LFENCE;
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_EIBRS_RETPOLINE:
|
||||
spectre_v2_enabled = SPECTRE_V2_EIBRS_RETPOLINE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init spectre_v2_update_mitigation(void)
|
||||
{
|
||||
if (spectre_v2_cmd == SPECTRE_V2_CMD_AUTO) {
|
||||
if (IS_ENABLED(CONFIG_MITIGATION_IBRS_ENTRY) &&
|
||||
boot_cpu_has_bug(X86_BUG_RETBLEED) &&
|
||||
retbleed_mitigation != RETBLEED_MITIGATION_NONE &&
|
||||
retbleed_mitigation != RETBLEED_MITIGATION_STUFF &&
|
||||
boot_cpu_has(X86_FEATURE_IBRS) &&
|
||||
boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
|
||||
mode = SPECTRE_V2_IBRS;
|
||||
break;
|
||||
spectre_v2_enabled = SPECTRE_V2_IBRS;
|
||||
}
|
||||
|
||||
mode = spectre_v2_select_retpoline();
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_RETPOLINE_LFENCE:
|
||||
pr_err(SPECTRE_V2_LFENCE_MSG);
|
||||
mode = SPECTRE_V2_LFENCE;
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_RETPOLINE_GENERIC:
|
||||
mode = SPECTRE_V2_RETPOLINE;
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_RETPOLINE:
|
||||
mode = spectre_v2_select_retpoline();
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_IBRS:
|
||||
mode = SPECTRE_V2_IBRS;
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_EIBRS:
|
||||
mode = SPECTRE_V2_EIBRS;
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_EIBRS_LFENCE:
|
||||
mode = SPECTRE_V2_EIBRS_LFENCE;
|
||||
break;
|
||||
|
||||
case SPECTRE_V2_CMD_EIBRS_RETPOLINE:
|
||||
mode = SPECTRE_V2_EIBRS_RETPOLINE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mode == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
|
||||
if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2) && !cpu_mitigations_off())
|
||||
pr_info("%s\n", spectre_v2_strings[spectre_v2_enabled]);
|
||||
}
|
||||
|
||||
static void __init spectre_v2_apply_mitigation(void)
|
||||
{
|
||||
if (spectre_v2_enabled == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
|
||||
pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
|
||||
|
||||
if (spectre_v2_in_ibrs_mode(mode)) {
|
||||
if (spectre_v2_in_ibrs_mode(spectre_v2_enabled)) {
|
||||
if (boot_cpu_has(X86_FEATURE_AUTOIBRS)) {
|
||||
msr_set_bit(MSR_EFER, _EFER_AUTOIBRS);
|
||||
} else {
|
||||
@ -1955,8 +1969,10 @@ static void __init spectre_v2_select_mitigation(void)
|
||||
}
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
switch (spectre_v2_enabled) {
|
||||
case SPECTRE_V2_NONE:
|
||||
return;
|
||||
|
||||
case SPECTRE_V2_EIBRS:
|
||||
break;
|
||||
|
||||
@ -1982,15 +1998,12 @@ static void __init spectre_v2_select_mitigation(void)
|
||||
* 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)
|
||||
if (spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE ||
|
||||
spectre_v2_enabled == SPECTRE_V2_EIBRS_RETPOLINE ||
|
||||
spectre_v2_enabled == SPECTRE_V2_RETPOLINE)
|
||||
spec_ctrl_disable_kernel_rrsba();
|
||||
|
||||
spectre_v2_enabled = mode;
|
||||
pr_info("%s\n", spectre_v2_strings[mode]);
|
||||
|
||||
spectre_v2_select_rsb_mitigation(mode);
|
||||
spectre_v2_select_rsb_mitigation(spectre_v2_enabled);
|
||||
|
||||
/*
|
||||
* Retpoline protects the kernel, but doesn't protect firmware. IBRS
|
||||
@ -1998,10 +2011,10 @@ static void __init spectre_v2_select_mitigation(void)
|
||||
* firmware calls only when IBRS / Enhanced / Automatic IBRS aren't
|
||||
* otherwise enabled.
|
||||
*
|
||||
* Use "mode" to check Enhanced IBRS instead of boot_cpu_has(), because
|
||||
* the user might select retpoline on the kernel command line and if
|
||||
* the CPU supports Enhanced IBRS, kernel might un-intentionally not
|
||||
* enable IBRS around firmware calls.
|
||||
* Use "spectre_v2_enabled" to check Enhanced IBRS instead of
|
||||
* boot_cpu_has(), because the user might select retpoline on the kernel
|
||||
* command line and if the CPU supports Enhanced IBRS, kernel might
|
||||
* un-intentionally not enable IBRS around firmware calls.
|
||||
*/
|
||||
if (boot_cpu_has_bug(X86_BUG_RETBLEED) &&
|
||||
boot_cpu_has(X86_FEATURE_IBPB) &&
|
||||
@ -2013,13 +2026,11 @@ static void __init spectre_v2_select_mitigation(void)
|
||||
pr_info("Enabling Speculation Barrier for firmware calls\n");
|
||||
}
|
||||
|
||||
} else if (boot_cpu_has(X86_FEATURE_IBRS) && !spectre_v2_in_ibrs_mode(mode)) {
|
||||
} else if (boot_cpu_has(X86_FEATURE_IBRS) &&
|
||||
!spectre_v2_in_ibrs_mode(spectre_v2_enabled)) {
|
||||
setup_force_cpu_cap(X86_FEATURE_USE_IBRS_FW);
|
||||
pr_info("Enabling Restricted Speculation for firmware calls\n");
|
||||
}
|
||||
|
||||
/* Set up IBPB and STIBP depending on the general spectre V2 command */
|
||||
spectre_v2_cmd = cmd;
|
||||
}
|
||||
|
||||
static void update_stibp_msr(void * __unused)
|
||||
|
Loading…
Reference in New Issue
Block a user