Re: [tip:x86/pti] x86/spectre: Add boot time option to select Spectre v2 mitigation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 1/10/2018 11:35 AM, tip-bot for David Woodhouse wrote:
> Commit-ID:  d569ded27d11bcb1643b14c54403910d9b3328b1
> Gitweb:     https://git.kernel.org/tip/d569ded27d11bcb1643b14c54403910d9b3328b1
> Author:     David Woodhouse <dwmw@xxxxxxxxxxxx>
> AuthorDate: Tue, 9 Jan 2018 14:43:09 +0000
> Committer:  Thomas Gleixner <tglx@xxxxxxxxxxxxx>
> CommitDate: Wed, 10 Jan 2018 18:28:22 +0100
> 
> x86/spectre: Add boot time option to select Spectre v2 mitigation
> 
> Add a spectre_v2= option to select the mitigation used for the indirect
> branch speculation vulnerability.
> 
> Currently, the only option available is retpoline, in its various forms.
> This will be expanded to cover the new IBRS/IBPB microcode features.
> 
> The RETPOLINE_AMD feature relies on a serializing LFENCE for speculation
> control. For AMD hardware, only set RETPOLINE_AMD if LFENCE is a
> serializing instruction, which is indicated by the LFENCE_RDTSC feature.
> 
> [ tglx: Folded back the LFENCE/AMD fixes and reworked it so IBRS
>   	integration becomes simple ]
> 
> Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx>
> Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
> Cc: gnomes@xxxxxxxxxxxxxxxxxxx
> Cc: Rik van Riel <riel@xxxxxxxxxx>
> Cc: Andi Kleen <ak@xxxxxxxxxxxxxxx>
> Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
> Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
> Cc: Jiri Kosina <jikos@xxxxxxxxxx>
> Cc: Andy Lutomirski <luto@xxxxxxxxxxxxxx>
> Cc: Dave Hansen <dave.hansen@xxxxxxxxx>
> Cc: Kees Cook <keescook@xxxxxxxxxx>
> Cc: Tim Chen <tim.c.chen@xxxxxxxxxxxxxxx>
> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxxx>
> Cc: Paul Turner <pjt@xxxxxxxxxx>
> Cc: Tom Lendacky <thomas.lendacky@xxxxxxx>
> Link: https://lkml.kernel.org/r/1515508997-6154-4-git-send-email-dwmw@xxxxxxxxxxxx
> 
> 
> ---
>  Documentation/admin-guide/kernel-parameters.txt |  28 +++++
>  arch/x86/include/asm/nospec-branch.h            |  10 ++
>  arch/x86/kernel/cpu/bugs.c                      | 158 +++++++++++++++++++++++-
>  arch/x86/kernel/cpu/common.c                    |   4 -
>  4 files changed, 195 insertions(+), 5 deletions(-)
> 

...

> diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
> index 76ad6cb..5b96fed 100644
> --- a/arch/x86/kernel/cpu/bugs.c
> +++ b/arch/x86/kernel/cpu/bugs.c
> @@ -11,6 +11,9 @@
>  #include <linux/init.h>
>  #include <linux/utsname.h>
>  #include <linux/cpu.h>
> +
> +#include <asm/nospec-branch.h>
> +#include <asm/cmdline.h>
>  #include <asm/bugs.h>
>  #include <asm/processor.h>
>  #include <asm/processor-flags.h>
> @@ -21,6 +24,8 @@
>  #include <asm/pgtable.h>
>  #include <asm/set_memory.h>
>  
> +static void __init spectre_v2_select_mitigation(void);
> +
>  void __init check_bugs(void)
>  {
>  	identify_boot_cpu();
> @@ -30,6 +35,9 @@ void __init check_bugs(void)
>  		print_cpu_info(&boot_cpu_data);
>  	}
>  
> +	/* Select the proper spectre mitigation before patching alternatives */
> +	spectre_v2_select_mitigation();
> +
>  #ifdef CONFIG_X86_32
>  	/*
>  	 * Check whether we are able to run this kernel safely on SMP.
> @@ -62,6 +70,153 @@ void __init check_bugs(void)
>  #endif
>  }
>  
> +/* The kernel command line selection */
> +enum spectre_v2_mitigation_cmd {
> +	SPECTRE_V2_CMD_NONE,
> +	SPECTRE_V2_CMD_AUTO,
> +	SPECTRE_V2_CMD_FORCE,
> +	SPECTRE_V2_CMD_RETPOLINE,
> +	SPECTRE_V2_CMD_RETPOLINE_GENERIC,
> +	SPECTRE_V2_CMD_RETPOLINE_AMD,
> +};
> +
> +static const char *spectre_v2_strings[] = {
> +	[SPECTRE_V2_NONE]			= "Vulnerable",
> +	[SPECTRE_V2_RETPOLINE_MINIMAL]		= "Vulnerable: Minimal generic ASM retpoline",
> +	[SPECTRE_V2_RETPOLINE_MINIMAL_AMD]	= "Vulnerable: Minimal AMD ASM retpoline",
> +	[SPECTRE_V2_RETPOLINE_GENERIC]		= "Mitigation: Full generic retpoline",
> +	[SPECTRE_V2_RETPOLINE_AMD]		= "Mitigation: Full AMD retpoline",
> +};
> +
> +#undef pr_fmt
> +#define pr_fmt(fmt)     "Spectre V2 mitigation: " fmt
> +
> +static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NONE;
> +
> +static void __init spec2_print_if_insecure(const char *reason)
> +{
> +	if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
> +		pr_info("%s\n", reason);
> +}
> +
> +static void __init spec2_print_if_secure(const char *reason)
> +{
> +	if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
> +		pr_info("%s\n", reason);
> +}
> +
> +static inline bool retp_compiler(void)
> +{
> +	return __is_defined(RETPOLINE);
> +}
> +
> +static inline bool match_option(const char *arg, int arglen, const char *opt)
> +{
> +	int len = strlen(opt);
> +
> +	return len == arglen && !strncmp(arg, opt, len);
> +}
> +
> +static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
> +{
> +	char arg[20];
> +	int ret;
> +
> +	ret = cmdline_find_option(boot_command_line, "spectre_v2", arg,
> +				  sizeof(arg));
> +	if (ret > 0)  {
> +		if (match_option(arg, ret, "off")) {
> +			goto disable;
> +		} else if (match_option(arg, ret, "on")) {
> +			spec2_print_if_secure("force enabled on command line.");
> +			return SPECTRE_V2_CMD_FORCE;
> +		} else if (match_option(arg, ret, "retpoline")) {
> +			spec2_print_if_insecure("retpoline selected on command line.");
> +			return SPECTRE_V2_CMD_RETPOLINE;
> +		} else if (match_option(arg, ret, "retpoline,amd")) {
> +			if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
> +				pr_err("retpoline,amd selected but CPU is not AMD. Switching to AUTO select\n");
> +				return SPECTRE_V2_CMD_AUTO;
> +			}
> +			if (!boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) {
> +				pr_err("LFENCE not serializing. Switching to generic retpoline\n");
> +				return SPECTRE_V2_CMD_RETPOLINE_GENERIC;
> +			}
> +			spec2_print_if_insecure("AMD retpoline selected on command line.");
> +			return SPECTRE_V2_CMD_RETPOLINE_AMD;
> +		} else if (match_option(arg, ret, "retpoline,generic")) {
> +			spec2_print_if_insecure("generic retpoline selected on command line.");
> +			return SPECTRE_V2_CMD_RETPOLINE_GENERIC;
> +		} else if (match_option(arg, ret, "auto")) {
> +			return SPECTRE_V2_CMD_AUTO;
> +		}
> +	}
> +
> +	if (!cmdline_find_option_bool(boot_command_line, "nospectre_v2"))
> +		return SPECTRE_V2_CMD_AUTO;
> +disable:
> +	spec2_print_if_insecure("disabled on command line.");
> +	return SPECTRE_V2_CMD_NONE;
> +}
> +
> +static void __init spectre_v2_select_mitigation(void)
> +{
> +	enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
> +	enum spectre_v2_mitigation mode = SPECTRE_V2_NONE;
> +
> +	/*
> +	 * If the CPU is not affected and the command line mode is NONE or AUTO
> +	 * then nothing to do.
> +	 */
> +	if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2) &&
> +	    (cmd == SPECTRE_V2_CMD_NONE || cmd == SPECTRE_V2_CMD_AUTO))
> +		return;
> +
> +	switch (cmd) {
> +	case SPECTRE_V2_CMD_NONE:
> +		return;
> +
> +	case SPECTRE_V2_CMD_FORCE:
> +		/* FALLTRHU */
> +	case SPECTRE_V2_CMD_AUTO:
> +		goto retpoline_auto;
> +
> +	case SPECTRE_V2_CMD_RETPOLINE_AMD:
> +		if (IS_ENABLED(CONFIG_RETPOLINE))
> +			goto retpoline_amd;
> +		break;
> +	case SPECTRE_V2_CMD_RETPOLINE_GENERIC:
> +		if (IS_ENABLED(CONFIG_RETPOLINE))
> +			goto retpoline_generic;
> +		break;
> +	case SPECTRE_V2_CMD_RETPOLINE:
> +		if (IS_ENABLED(CONFIG_RETPOLINE))
> +			goto retpoline_auto;
> +		break;
> +	}
> +	pr_err("kernel not compiled with retpoline; no mitigation available!");
> +	return;
> +
> +retpoline_auto:
> +	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {

Not specifying anything on the command line will get SPECTRE_V2_CMD_AUTO,
so boot_cpu_has(X86_FEATURE_LFENCE_RDTSC) needs to be checked since it
won't have been checked previously.

Thanks,
Tom

> +	retpoline_amd:
> +		mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_AMD :
> +					 SPECTRE_V2_RETPOLINE_MINIMAL_AMD;
> +		setup_force_cpu_cap(X86_FEATURE_RETPOLINE_AMD);
> +		setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
> +	} else {
> +	retpoline_generic:
> +		mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_GENERIC :
> +					 SPECTRE_V2_RETPOLINE_MINIMAL;
> +		setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
> +	}
> +
> +	spectre_v2_enabled = mode;
> +	pr_info("%s\n", spectre_v2_strings[mode]);
> +}
> +
> +#undef pr_fmt
> +
>  #ifdef CONFIG_SYSFS
>  ssize_t cpu_show_meltdown(struct device *dev,
>  			  struct device_attribute *attr, char *buf)
> @@ -86,6 +241,7 @@ ssize_t cpu_show_spectre_v2(struct device *dev,
>  {
>  	if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
>  		return sprintf(buf, "Not affected\n");
> -	return sprintf(buf, "Vulnerable\n");
> +
> +	return sprintf(buf, "%s\n", spectre_v2_strings[spectre_v2_enabled]);
>  }
>  #endif
> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> index 7a671d1..372ba3f 100644
> --- a/arch/x86/kernel/cpu/common.c
> +++ b/arch/x86/kernel/cpu/common.c
> @@ -905,10 +905,6 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
>  	setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
>  	setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
>  
> -#ifdef CONFIG_RETPOLINE
> -	setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
> -#endif
> -
>  	fpu__init_system(c);
>  
>  #ifdef CONFIG_X86_32
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Stable Commits]     [Linux Stable Kernel]     [Linux Kernel]     [Linux USB Devel]     [Linux Video &Media]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux