x86/bugs: Enable STIBP for JMP2RET
commit e8ec1b6e08a2102d8755ccb06fa26d540f26a2fa upstream. For untrained return thunks to be fully effective, STIBP must be enabled or SMT disabled. Co-developed-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Kim Phillips <kim.phillips@amd.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Borislav Petkov <bp@suse.de> Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
3f29791d56
commit
a989e75136
@@ -4660,11 +4660,17 @@
|
|||||||
Speculative Code Execution with Return Instructions)
|
Speculative Code Execution with Return Instructions)
|
||||||
vulnerability.
|
vulnerability.
|
||||||
|
|
||||||
off - unconditionally disable
|
off - no mitigation
|
||||||
auto - automatically select a migitation
|
auto - automatically select a migitation
|
||||||
unret - force enable untrained return thunks,
|
auto,nosmt - automatically select a mitigation,
|
||||||
only effective on AMD Zen {1,2}
|
disabling SMT if necessary for
|
||||||
based systems.
|
the full mitigation (only on Zen1
|
||||||
|
and older without STIBP).
|
||||||
|
unret - force enable untrained return thunks,
|
||||||
|
only effective on AMD f15h-f17h
|
||||||
|
based systems.
|
||||||
|
unret,nosmt - like unret, will disable SMT when STIBP
|
||||||
|
is not available.
|
||||||
|
|
||||||
Selecting 'auto' will choose a mitigation method at run
|
Selecting 'auto' will choose a mitigation method at run
|
||||||
time according to the CPU.
|
time according to the CPU.
|
||||||
|
@@ -739,19 +739,34 @@ static enum retbleed_mitigation retbleed_mitigation __ro_after_init =
|
|||||||
static enum retbleed_mitigation_cmd retbleed_cmd __ro_after_init =
|
static enum retbleed_mitigation_cmd retbleed_cmd __ro_after_init =
|
||||||
RETBLEED_CMD_AUTO;
|
RETBLEED_CMD_AUTO;
|
||||||
|
|
||||||
|
static int __ro_after_init retbleed_nosmt = false;
|
||||||
|
|
||||||
static int __init retbleed_parse_cmdline(char *str)
|
static int __init retbleed_parse_cmdline(char *str)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!strcmp(str, "off"))
|
while (str) {
|
||||||
retbleed_cmd = RETBLEED_CMD_OFF;
|
char *next = strchr(str, ',');
|
||||||
else if (!strcmp(str, "auto"))
|
if (next) {
|
||||||
retbleed_cmd = RETBLEED_CMD_AUTO;
|
*next = 0;
|
||||||
else if (!strcmp(str, "unret"))
|
next++;
|
||||||
retbleed_cmd = RETBLEED_CMD_UNRET;
|
}
|
||||||
else
|
|
||||||
pr_err("Unknown retbleed option (%s). Defaulting to 'auto'\n", str);
|
if (!strcmp(str, "off")) {
|
||||||
|
retbleed_cmd = RETBLEED_CMD_OFF;
|
||||||
|
} else if (!strcmp(str, "auto")) {
|
||||||
|
retbleed_cmd = RETBLEED_CMD_AUTO;
|
||||||
|
} else if (!strcmp(str, "unret")) {
|
||||||
|
retbleed_cmd = RETBLEED_CMD_UNRET;
|
||||||
|
} else if (!strcmp(str, "nosmt")) {
|
||||||
|
retbleed_nosmt = true;
|
||||||
|
} else {
|
||||||
|
pr_err("Ignoring unknown retbleed option (%s).", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
str = next;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -797,6 +812,10 @@ static void __init retbleed_select_mitigation(void)
|
|||||||
setup_force_cpu_cap(X86_FEATURE_RETHUNK);
|
setup_force_cpu_cap(X86_FEATURE_RETHUNK);
|
||||||
setup_force_cpu_cap(X86_FEATURE_UNRET);
|
setup_force_cpu_cap(X86_FEATURE_UNRET);
|
||||||
|
|
||||||
|
if (!boot_cpu_has(X86_FEATURE_STIBP) &&
|
||||||
|
(retbleed_nosmt || cpu_mitigations_auto_nosmt()))
|
||||||
|
cpu_smt_disable(false);
|
||||||
|
|
||||||
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
|
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
|
||||||
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
|
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
|
||||||
pr_err(RETBLEED_UNTRAIN_MSG);
|
pr_err(RETBLEED_UNTRAIN_MSG);
|
||||||
@@ -1043,6 +1062,13 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
|
|||||||
boot_cpu_has(X86_FEATURE_AMD_STIBP_ALWAYS_ON))
|
boot_cpu_has(X86_FEATURE_AMD_STIBP_ALWAYS_ON))
|
||||||
mode = SPECTRE_V2_USER_STRICT_PREFERRED;
|
mode = SPECTRE_V2_USER_STRICT_PREFERRED;
|
||||||
|
|
||||||
|
if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET) {
|
||||||
|
if (mode != SPECTRE_V2_USER_STRICT &&
|
||||||
|
mode != SPECTRE_V2_USER_STRICT_PREFERRED)
|
||||||
|
pr_info("Selecting STIBP always-on mode to complement retbleed mitigation'\n");
|
||||||
|
mode = SPECTRE_V2_USER_STRICT_PREFERRED;
|
||||||
|
}
|
||||||
|
|
||||||
spectre_v2_user_stibp = mode;
|
spectre_v2_user_stibp = mode;
|
||||||
|
|
||||||
set_mode:
|
set_mode:
|
||||||
@@ -2020,10 +2046,18 @@ static ssize_t srbds_show_state(char *buf)
|
|||||||
|
|
||||||
static ssize_t retbleed_show_state(char *buf)
|
static ssize_t retbleed_show_state(char *buf)
|
||||||
{
|
{
|
||||||
if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET &&
|
if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET) {
|
||||||
(boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
|
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
|
||||||
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON))
|
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
|
||||||
return sprintf(buf, "Vulnerable: untrained return thunk on non-Zen uarch\n");
|
return sprintf(buf, "Vulnerable: untrained return thunk on non-Zen uarch\n");
|
||||||
|
|
||||||
|
return sprintf(buf, "%s; SMT %s\n",
|
||||||
|
retbleed_strings[retbleed_mitigation],
|
||||||
|
!sched_smt_active() ? "disabled" :
|
||||||
|
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
|
||||||
|
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ?
|
||||||
|
"enabled with STIBP protection" : "vulnerable");
|
||||||
|
}
|
||||||
|
|
||||||
return sprintf(buf, "%s\n", retbleed_strings[retbleed_mitigation]);
|
return sprintf(buf, "%s\n", retbleed_strings[retbleed_mitigation]);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user