Commit 7fbf47c7 authored by Alexandre Chartre's avatar Alexandre Chartre Committed by Borislav Petkov
Browse files

x86/bugs: Add AMD retbleed= boot parameter



Add the "retbleed=<value>" boot parameter to select a mitigation for
RETBleed. Possible values are "off", "auto" and "unret"
(JMP2RET mitigation). The default value is "auto".

Currently, "retbleed=auto" will select the unret mitigation on
AMD and Hygon and no mitigation on Intel (JMP2RET is not effective on
Intel).

  [peterz: rebase; add hygon]
  [jpoimboe: cleanups]

Signed-off-by: default avatarAlexandre Chartre <alexandre.chartre@oracle.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarJosh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
parent 6b80b59b
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -5197,6 +5197,21 @@

	retain_initrd	[RAM] Keep initrd memory after extraction

	retbleed=	[X86] Control mitigation of RETBleed (Arbitrary
			Speculative Code Execution with Return Instructions)
			vulnerability.

			off         - unconditionally disable
			auto        - automatically select a migitation
			unret       - force enable untrained return thunks,
				      only effective on AMD Zen {1,2}
				      based systems.

			Selecting 'auto' will choose a mitigation method at run
			time according to the CPU.

			Not specifying this option is equivalent to retbleed=auto.

	rfkill.default_state=
		0	"airplane mode".  All wifi, bluetooth, wimax, gps, fm,
			etc. communication is blocked by default.
+3 −0
Original line number Diff line number Diff line
@@ -475,6 +475,9 @@ config RETPOLINE
config CC_HAS_SLS
	def_bool $(cc-option,-mharden-sls=all)

config CC_HAS_RETURN_THUNK
	def_bool $(cc-option,-mfunction-return=thunk-extern)

config SLS
	bool "Mitigate Straight-Line-Speculation"
	depends on CC_HAS_SLS && X86_64
+107 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "cpu.h"

static void __init spectre_v1_select_mitigation(void);
static void __init retbleed_select_mitigation(void);
static void __init spectre_v2_select_mitigation(void);
static void __init ssb_select_mitigation(void);
static void __init l1tf_select_mitigation(void);
@@ -120,6 +121,12 @@ void __init check_bugs(void)

	/* Select the proper CPU mitigations before patching alternatives: */
	spectre_v1_select_mitigation();
	retbleed_select_mitigation();
	/*
	 * spectre_v2_select_mitigation() relies on the state set by
	 * retbleed_select_mitigation(); specifically the STIBP selection is
	 * forced for UNRET.
	 */
	spectre_v2_select_mitigation();
	ssb_select_mitigation();
	l1tf_select_mitigation();
@@ -752,6 +759,100 @@ static int __init nospectre_v1_cmdline(char *str)
}
early_param("nospectre_v1", nospectre_v1_cmdline);

#undef pr_fmt
#define pr_fmt(fmt)     "RETBleed: " fmt

enum retbleed_mitigation {
	RETBLEED_MITIGATION_NONE,
	RETBLEED_MITIGATION_UNRET,
};

enum retbleed_mitigation_cmd {
	RETBLEED_CMD_OFF,
	RETBLEED_CMD_AUTO,
	RETBLEED_CMD_UNRET,
};

const char * const retbleed_strings[] = {
	[RETBLEED_MITIGATION_NONE]	= "Vulnerable",
	[RETBLEED_MITIGATION_UNRET]	= "Mitigation: untrained return thunk",
};

static enum retbleed_mitigation retbleed_mitigation __ro_after_init =
	RETBLEED_MITIGATION_NONE;
static enum retbleed_mitigation_cmd retbleed_cmd __ro_after_init =
	RETBLEED_CMD_AUTO;

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

	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
		pr_err("Unknown retbleed option (%s). Defaulting to 'auto'\n", str);

	return 0;
}
early_param("retbleed", retbleed_parse_cmdline);

#define RETBLEED_UNTRAIN_MSG "WARNING: BTB untrained return thunk mitigation is only effective on AMD/Hygon!\n"
#define RETBLEED_COMPILER_MSG "WARNING: kernel not compiled with RETPOLINE or -mfunction-return capable compiler!\n"

static void __init retbleed_select_mitigation(void)
{
	if (!boot_cpu_has_bug(X86_BUG_RETBLEED) || cpu_mitigations_off())
		return;

	switch (retbleed_cmd) {
	case RETBLEED_CMD_OFF:
		return;

	case RETBLEED_CMD_UNRET:
		retbleed_mitigation = RETBLEED_MITIGATION_UNRET;
		break;

	case RETBLEED_CMD_AUTO:
	default:
		if (!boot_cpu_has_bug(X86_BUG_RETBLEED))
			break;

		if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
		    boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
			retbleed_mitigation = RETBLEED_MITIGATION_UNRET;
		break;
	}

	switch (retbleed_mitigation) {
	case RETBLEED_MITIGATION_UNRET:

		if (!IS_ENABLED(CONFIG_RETPOLINE) ||
		    !IS_ENABLED(CONFIG_CC_HAS_RETURN_THUNK)) {
			pr_err(RETBLEED_COMPILER_MSG);
			retbleed_mitigation = RETBLEED_MITIGATION_NONE;
			break;
		}

		setup_force_cpu_cap(X86_FEATURE_RETHUNK);
		setup_force_cpu_cap(X86_FEATURE_UNRET);

		if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
		    boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
			pr_err(RETBLEED_UNTRAIN_MSG);
		break;

	default:
		break;
	}

	pr_info("%s\n", retbleed_strings[retbleed_mitigation]);
}

#undef pr_fmt
#define pr_fmt(fmt)     "Spectre V2 : " fmt

@@ -1996,7 +2097,12 @@ static ssize_t srbds_show_state(char *buf)

static ssize_t retbleed_show_state(char *buf)
{
	return sprintf(buf, "Vulnerable\n");
	if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET &&
	    (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\n", retbleed_strings[retbleed_mitigation]);
}

static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,