Commit 02ac6cc8 authored by David Kaplan's avatar David Kaplan Committed by Borislav Petkov (AMD)
Browse files

x86/bugs: Simplify SSB cmdline parsing



Simplify the SSB command line parsing by selecting a mitigation directly, as
is done in most of the simpler vulnerabilities.  Use early_param() instead of
cmdline_find_option() for consistency with the other mitigation selections.

Signed-off-by: default avatarDavid Kaplan <david.kaplan@amd.com>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: default avatarPawan Gupta <pawan.kumar.gupta@linux.intel.com>
Link: https://lore.kernel.org/r/20250819192200.2003074-4-david.kaplan@amd.com
parent 9a9f8147
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -514,6 +514,7 @@ enum spectre_v2_user_mitigation {
/* The Speculative Store Bypass disable variants */
enum ssb_mitigation {
	SPEC_STORE_BYPASS_NONE,
	SPEC_STORE_BYPASS_AUTO,
	SPEC_STORE_BYPASS_DISABLE,
	SPEC_STORE_BYPASS_PRCTL,
	SPEC_STORE_BYPASS_SECCOMP,
+40 −80
Original line number Diff line number Diff line
@@ -2525,16 +2525,8 @@ static void update_mds_branch_idle(void)
#undef pr_fmt
#define pr_fmt(fmt)	"Speculative Store Bypass: " fmt

static enum ssb_mitigation ssb_mode __ro_after_init = SPEC_STORE_BYPASS_NONE;

/* The kernel command line selection */
enum ssb_mitigation_cmd {
	SPEC_STORE_BYPASS_CMD_NONE,
	SPEC_STORE_BYPASS_CMD_AUTO,
	SPEC_STORE_BYPASS_CMD_ON,
	SPEC_STORE_BYPASS_CMD_PRCTL,
	SPEC_STORE_BYPASS_CMD_SECCOMP,
};
static enum ssb_mitigation ssb_mode __ro_after_init =
	IS_ENABLED(CONFIG_MITIGATION_SSB) ? SPEC_STORE_BYPASS_AUTO : SPEC_STORE_BYPASS_NONE;

static const char * const ssb_strings[] = {
	[SPEC_STORE_BYPASS_NONE]	= "Vulnerable",
@@ -2543,93 +2535,60 @@ static const char * const ssb_strings[] = {
	[SPEC_STORE_BYPASS_SECCOMP]	= "Mitigation: Speculative Store Bypass disabled via prctl and seccomp",
};

static const struct {
	const char *option;
	enum ssb_mitigation_cmd cmd;
} ssb_mitigation_options[]  __initconst = {
	{ "auto",	SPEC_STORE_BYPASS_CMD_AUTO },    /* Platform decides */
	{ "on",		SPEC_STORE_BYPASS_CMD_ON },      /* Disable Speculative Store Bypass */
	{ "off",	SPEC_STORE_BYPASS_CMD_NONE },    /* Don't touch Speculative Store Bypass */
	{ "prctl",	SPEC_STORE_BYPASS_CMD_PRCTL },   /* Disable Speculative Store Bypass via prctl */
	{ "seccomp",	SPEC_STORE_BYPASS_CMD_SECCOMP }, /* Disable Speculative Store Bypass via prctl and seccomp */
};
static bool nossb __ro_after_init;

static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
static int __init nossb_parse_cmdline(char *str)
{
	enum ssb_mitigation_cmd cmd;
	char arg[20];
	int ret, i;

	cmd = IS_ENABLED(CONFIG_MITIGATION_SSB) ?
		SPEC_STORE_BYPASS_CMD_AUTO : SPEC_STORE_BYPASS_CMD_NONE;
	if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable") ||
	    cpu_mitigations_off()) {
		return SPEC_STORE_BYPASS_CMD_NONE;
	} else {
		ret = cmdline_find_option(boot_command_line, "spec_store_bypass_disable",
					  arg, sizeof(arg));
		if (ret < 0)
			return cmd;
	nossb = true;
	ssb_mode = SPEC_STORE_BYPASS_NONE;
	return 0;
}
early_param("nospec_store_bypass_disable", nossb_parse_cmdline);

		for (i = 0; i < ARRAY_SIZE(ssb_mitigation_options); i++) {
			if (!match_option(arg, ret, ssb_mitigation_options[i].option))
				continue;
static int __init ssb_parse_cmdline(char *str)
{
	if (!str)
		return -EINVAL;

			cmd = ssb_mitigation_options[i].cmd;
			break;
		}
	if (nossb)
		return 0;

		if (i >= ARRAY_SIZE(ssb_mitigation_options)) {
			pr_err("unknown option (%s). Switching to default mode\n", arg);
			return cmd;
		}
	}
	if (!strcmp(str, "auto"))
		ssb_mode = SPEC_STORE_BYPASS_AUTO;
	else if (!strcmp(str, "on"))
		ssb_mode = SPEC_STORE_BYPASS_DISABLE;
	else if (!strcmp(str, "off"))
		ssb_mode = SPEC_STORE_BYPASS_NONE;
	else if (!strcmp(str, "prctl"))
		ssb_mode = SPEC_STORE_BYPASS_PRCTL;
	else if (!strcmp(str, "seccomp"))
		ssb_mode = IS_ENABLED(CONFIG_SECCOMP) ?
			SPEC_STORE_BYPASS_SECCOMP : SPEC_STORE_BYPASS_PRCTL;
	else
		pr_err("Ignoring unknown spec_store_bypass_disable option (%s).\n",
			str);

	return cmd;
	return 0;
}
early_param("spec_store_bypass_disable", ssb_parse_cmdline);

static void __init ssb_select_mitigation(void)
{
	enum ssb_mitigation_cmd cmd;

	if (!boot_cpu_has(X86_FEATURE_SSBD))
		goto out;

	cmd = ssb_parse_cmdline();
	if (!boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS) &&
	    (cmd == SPEC_STORE_BYPASS_CMD_NONE ||
	     cmd == SPEC_STORE_BYPASS_CMD_AUTO))
	if (!boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS)) {
		ssb_mode = SPEC_STORE_BYPASS_NONE;
		return;
	}

	switch (cmd) {
	case SPEC_STORE_BYPASS_CMD_SECCOMP:
		/*
		 * Choose prctl+seccomp as the default mode if seccomp is
		 * enabled.
		 */
		if (IS_ENABLED(CONFIG_SECCOMP))
			ssb_mode = SPEC_STORE_BYPASS_SECCOMP;
		else
			ssb_mode = SPEC_STORE_BYPASS_PRCTL;
		break;
	case SPEC_STORE_BYPASS_CMD_ON:
		ssb_mode = SPEC_STORE_BYPASS_DISABLE;
		break;
	case SPEC_STORE_BYPASS_CMD_AUTO:
	if (ssb_mode == SPEC_STORE_BYPASS_AUTO) {
		if (should_mitigate_vuln(X86_BUG_SPEC_STORE_BYPASS))
			ssb_mode = SPEC_STORE_BYPASS_PRCTL;
		else
			ssb_mode = SPEC_STORE_BYPASS_NONE;
		break;
	case SPEC_STORE_BYPASS_CMD_PRCTL:
		ssb_mode = SPEC_STORE_BYPASS_PRCTL;
		break;
	case SPEC_STORE_BYPASS_CMD_NONE:
		break;
	}

out:
	if (boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS))
	if (!boot_cpu_has(X86_FEATURE_SSBD))
		ssb_mode = SPEC_STORE_BYPASS_NONE;

	pr_info("%s\n", ssb_strings[ssb_mode]);
}

@@ -2846,6 +2805,7 @@ static int ssb_prctl_get(struct task_struct *task)
		return PR_SPEC_DISABLE;
	case SPEC_STORE_BYPASS_SECCOMP:
	case SPEC_STORE_BYPASS_PRCTL:
	case SPEC_STORE_BYPASS_AUTO:
		if (task_spec_ssb_force_disable(task))
			return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
		if (task_spec_ssb_noexec(task))