Commit e8ec1b6e authored by Kim Phillips's avatar Kim Phillips Committed by Borislav Petkov
Browse files

x86/bugs: Enable STIBP for JMP2RET



For untrained return thunks to be fully effective, STIBP must be enabled
or SMT disabled.

Co-developed-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: default avatarKim Phillips <kim.phillips@amd.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
parent 7fbf47c7
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -5201,11 +5201,17 @@
			Speculative Code Execution with Return Instructions)
			vulnerability.

			off         - unconditionally disable
			off          - no mitigation
			auto         - automatically select a migitation
			auto,nosmt   - automatically select a mitigation,
				       disabling SMT if necessary for
				       the full mitigation (only on Zen1
				       and older without STIBP).
			unret        - force enable untrained return thunks,
				      only effective on AMD Zen {1,2}
				       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
			time according to the CPU.
+46 −12
Original line number Diff line number Diff line
@@ -783,19 +783,34 @@ static enum retbleed_mitigation retbleed_mitigation __ro_after_init =
static enum retbleed_mitigation_cmd retbleed_cmd __ro_after_init =
	RETBLEED_CMD_AUTO;

static int __ro_after_init retbleed_nosmt = false;

static int __init retbleed_parse_cmdline(char *str)
{
	if (!str)
		return -EINVAL;

	if (!strcmp(str, "off"))
	while (str) {
		char *next = strchr(str, ',');
		if (next) {
			*next = 0;
			next++;
		}

		if (!strcmp(str, "off")) {
			retbleed_cmd = RETBLEED_CMD_OFF;
	else if (!strcmp(str, "auto"))
		} else if (!strcmp(str, "auto")) {
			retbleed_cmd = RETBLEED_CMD_AUTO;
	else if (!strcmp(str, "unret"))
		} else if (!strcmp(str, "unret")) {
			retbleed_cmd = RETBLEED_CMD_UNRET;
	else
		pr_err("Unknown retbleed option (%s). Defaulting to 'auto'\n", str);
		} else if (!strcmp(str, "nosmt")) {
			retbleed_nosmt = true;
		} else {
			pr_err("Ignoring unknown retbleed option (%s).", str);
		}

		str = next;
	}

	return 0;
}
@@ -841,6 +856,10 @@ static void __init retbleed_select_mitigation(void)
		setup_force_cpu_cap(X86_FEATURE_RETHUNK);
		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 &&
		    boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
			pr_err(RETBLEED_UNTRAIN_MSG);
@@ -1087,6 +1106,13 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
	    boot_cpu_has(X86_FEATURE_AMD_STIBP_ALWAYS_ON))
		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;

set_mode:
@@ -2097,11 +2123,19 @@ static ssize_t srbds_show_state(char *buf)

static ssize_t retbleed_show_state(char *buf)
{
	if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET &&
	    (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
	     boot_cpu_data.x86_vendor != X86_VENDOR_HYGON))
	if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET) {
	    if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
		boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
		    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]);
}