Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7cc765a6 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

x86/speculation: Enable prctl mode for spectre_v2_user



Now that all prerequisites are in place:

 - Add the prctl command line option

 - Default the 'auto' mode to 'prctl'

 - When SMT state changes, update the static key which controls the
   conditional STIBP evaluation on context switch.

 - At init update the static key which controls the conditional IBPB
   evaluation on context switch.

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarIngo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: David Woodhouse <dwmw@amazon.co.uk>
Cc: Tim Chen <tim.c.chen@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Casey Schaufler <casey.schaufler@intel.com>
Cc: Asit Mallick <asit.k.mallick@intel.com>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Jon Masters <jcm@redhat.com>
Cc: Waiman Long <longman9394@gmail.com>
Cc: Greg KH <gregkh@linuxfoundation.org>
Cc: Dave Stewart <david.c.stewart@intel.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20181125185005.958421388@linutronix.de
parent 9137bb27
Loading
Loading
Loading
Loading
+6 −1
Original line number Original line Diff line number Diff line
@@ -4236,9 +4236,14 @@
			off     - Unconditionally disable mitigations. Is
			off     - Unconditionally disable mitigations. Is
				  enforced by spectre_v2=off
				  enforced by spectre_v2=off


			prctl   - Indirect branch speculation is enabled,
				  but mitigation can be enabled via prctl
				  per thread.  The mitigation control state
				  is inherited on fork.

			auto    - Kernel selects the mitigation depending on
			auto    - Kernel selects the mitigation depending on
				  the available CPU features and vulnerability.
				  the available CPU features and vulnerability.
				  Default is off.
				  Default is prctl.


			Not specifying this option is equivalent to
			Not specifying this option is equivalent to
			spectre_v2_user=auto.
			spectre_v2_user=auto.
+32 −9
Original line number Original line Diff line number Diff line
@@ -255,11 +255,13 @@ enum spectre_v2_user_cmd {
	SPECTRE_V2_USER_CMD_NONE,
	SPECTRE_V2_USER_CMD_NONE,
	SPECTRE_V2_USER_CMD_AUTO,
	SPECTRE_V2_USER_CMD_AUTO,
	SPECTRE_V2_USER_CMD_FORCE,
	SPECTRE_V2_USER_CMD_FORCE,
	SPECTRE_V2_USER_CMD_PRCTL,
};
};


static const char * const spectre_v2_user_strings[] = {
static const char * const spectre_v2_user_strings[] = {
	[SPECTRE_V2_USER_NONE]		= "User space: Vulnerable",
	[SPECTRE_V2_USER_NONE]		= "User space: Vulnerable",
	[SPECTRE_V2_USER_STRICT]	= "User space: Mitigation: STIBP protection",
	[SPECTRE_V2_USER_STRICT]	= "User space: Mitigation: STIBP protection",
	[SPECTRE_V2_USER_PRCTL]		= "User space: Mitigation: STIBP via prctl",
};
};


static const struct {
static const struct {
@@ -270,6 +272,7 @@ static const struct {
	{ "auto",	SPECTRE_V2_USER_CMD_AUTO,	false },
	{ "auto",	SPECTRE_V2_USER_CMD_AUTO,	false },
	{ "off",	SPECTRE_V2_USER_CMD_NONE,	false },
	{ "off",	SPECTRE_V2_USER_CMD_NONE,	false },
	{ "on",		SPECTRE_V2_USER_CMD_FORCE,	true  },
	{ "on",		SPECTRE_V2_USER_CMD_FORCE,	true  },
	{ "prctl",	SPECTRE_V2_USER_CMD_PRCTL,	false },
};
};


static void __init spec_v2_user_print_cond(const char *reason, bool secure)
static void __init spec_v2_user_print_cond(const char *reason, bool secure)
@@ -324,12 +327,15 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
		smt_possible = false;
		smt_possible = false;


	switch (spectre_v2_parse_user_cmdline(v2_cmd)) {
	switch (spectre_v2_parse_user_cmdline(v2_cmd)) {
	case SPECTRE_V2_USER_CMD_AUTO:
	case SPECTRE_V2_USER_CMD_NONE:
	case SPECTRE_V2_USER_CMD_NONE:
		goto set_mode;
		goto set_mode;
	case SPECTRE_V2_USER_CMD_FORCE:
	case SPECTRE_V2_USER_CMD_FORCE:
		mode = SPECTRE_V2_USER_STRICT;
		mode = SPECTRE_V2_USER_STRICT;
		break;
		break;
	case SPECTRE_V2_USER_CMD_AUTO:
	case SPECTRE_V2_USER_CMD_PRCTL:
		mode = SPECTRE_V2_USER_PRCTL;
		break;
	}
	}


	/* Initialize Indirect Branch Prediction Barrier */
	/* Initialize Indirect Branch Prediction Barrier */
@@ -340,6 +346,9 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
		case SPECTRE_V2_USER_STRICT:
		case SPECTRE_V2_USER_STRICT:
			static_branch_enable(&switch_mm_always_ibpb);
			static_branch_enable(&switch_mm_always_ibpb);
			break;
			break;
		case SPECTRE_V2_USER_PRCTL:
			static_branch_enable(&switch_mm_cond_ibpb);
			break;
		default:
		default:
			break;
			break;
		}
		}
@@ -352,6 +361,12 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
	if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
	if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
		return;
		return;


	/*
	 * If SMT is not possible or STIBP is not available clear the STIPB
	 * mode.
	 */
	if (!smt_possible || !boot_cpu_has(X86_FEATURE_STIBP))
		mode = SPECTRE_V2_USER_NONE;
set_mode:
set_mode:
	spectre_v2_user = mode;
	spectre_v2_user = mode;
	/* Only print the STIBP mode when SMT possible */
	/* Only print the STIBP mode when SMT possible */
@@ -552,6 +567,15 @@ static void update_stibp_strict(void)
	on_each_cpu(update_stibp_msr, NULL, 1);
	on_each_cpu(update_stibp_msr, NULL, 1);
}
}


/* Update the static key controlling the evaluation of TIF_SPEC_IB */
static void update_indir_branch_cond(void)
{
	if (sched_smt_active())
		static_branch_enable(&switch_to_cond_stibp);
	else
		static_branch_disable(&switch_to_cond_stibp);
}

void arch_smt_update(void)
void arch_smt_update(void)
{
{
	/* Enhanced IBRS implies STIBP. No update required. */
	/* Enhanced IBRS implies STIBP. No update required. */
@@ -567,6 +591,7 @@ void arch_smt_update(void)
		update_stibp_strict();
		update_stibp_strict();
		break;
		break;
	case SPECTRE_V2_USER_PRCTL:
	case SPECTRE_V2_USER_PRCTL:
		update_indir_branch_cond();
		break;
		break;
	}
	}


@@ -1038,7 +1063,8 @@ static char *stibp_state(void)
	case SPECTRE_V2_USER_STRICT:
	case SPECTRE_V2_USER_STRICT:
		return ", STIBP: forced";
		return ", STIBP: forced";
	case SPECTRE_V2_USER_PRCTL:
	case SPECTRE_V2_USER_PRCTL:
		return "";
		if (static_key_enabled(&switch_to_cond_stibp))
			return ", STIBP: conditional";
	}
	}
	return "";
	return "";
}
}
@@ -1046,14 +1072,11 @@ static char *stibp_state(void)
static char *ibpb_state(void)
static char *ibpb_state(void)
{
{
	if (boot_cpu_has(X86_FEATURE_IBPB)) {
	if (boot_cpu_has(X86_FEATURE_IBPB)) {
		switch (spectre_v2_user) {
		if (static_key_enabled(&switch_mm_always_ibpb))
		case SPECTRE_V2_USER_NONE:
			return ", IBPB: disabled";
		case SPECTRE_V2_USER_STRICT:
			return ", IBPB: always-on";
			return ", IBPB: always-on";
		case SPECTRE_V2_USER_PRCTL:
		if (static_key_enabled(&switch_mm_cond_ibpb))
			return "";
			return ", IBPB: conditional";
		}
		return ", IBPB: disabled";
	}
	}
	return "";
	return "";
}
}