[MODERATED] [PATCH RFC 4/4] 4
Josh Poimboeuf <[email protected]>
| Newsgroups | org.kernel.lore.historical-speck |
|---|---|
| Message-ID | <20190304012529.vlwghtse56qvnigx@treble> |
From: Josh Poimboeuf <[email protected]> Subject: [PATCH RFC 4/4] x86/speculation: Add 'cpu_spec_mitigations=' cmdline options Keeping track of the number of mitigations for all the CPU speculation bugs has become overwhelming for many users. It's getting more and more complicated to decide what mitigations are needed for a given architecture. Most users fall into a few basic categories: - want all mitigations off; - want all reasonable mitigations on, with SMT enabled even if it's vulnerable; or - want all reasonable mitigations on, with SMT disabled if vulnerable. Define a set of curated, arch-independent options, each of which is an aggregation of existing options: - cpu_spec_mitigations=off: Disable all mitigations. - cpu_spec_mitigations=auto: [default] Enable all the default mitigations, but leave SMT enabled, even if it's vulnerable. - cpu_spec_mitigations=auto,nosmt: Enable all the default mitigations, disabling SMT if needed by a mitigation. See the documentation for more details. Signed-off-by: Josh Poimboeuf <[email protected]> --- .../admin-guide/kernel-parameters.txt | 43 ++++++++++++++++ arch/powerpc/kernel/security.c | 6 +-- arch/powerpc/kernel/setup_64.c | 2 +- arch/s390/kernel/nospec-branch.c | 4 +- arch/x86/include/asm/processor.h | 2 + arch/x86/kernel/cpu/bugs.c | 51 ++++++++++++++++--- arch/x86/mm/pti.c | 3 +- include/linux/cpu.h | 8 +++ kernel/cpu.c | 15 ++++++ 9 files changed, 122 insertions(+), 12 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 55969f240f2e..c2dba60630e4 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2537,6 +2537,49 @@ in the "bleeding edge" mini2440 support kernel at http://repo.or.cz/w/linux-2.6/mini2440.git + cpu_spec_mitigations= + [KNL] Control mitigations for CPU speculation + vulnerabilities on affected CPUs. This is a set of + curated, arch-independent options, each of which is an + aggregation of existing options. + + off + Disable all speculative CPU mitigations. + Equivalent to: nopti + nospectre_v1 + nospectre_v2 + spectre_v2_user=off + nobp=0 + spec_store_bypass_disable=off + l1tf=off + mds=off + + auto (default) + Mitigate all speculative CPU vulnerabilities, + but leave SMT enabled, even if it's vulnerable. + This is useful for users who don't want to be + surprised by SMT getting disabled across kernel + upgrades, or who have other ways of avoiding + SMT-based attacks. + Equivalent to: pti=auto + spectre_v2=auto + spectre_v2_user=auto + spec_store_bypass_disable=auto + l1tf=flush + mds=full + + auto,nosmt + Mitigate all speculative CPU vulnerabilities, + disabling SMT if needed. This is for users who + always want to be fully mitigated, even if it + means losing SMT. + Equivalent to: pti=auto + spectre_v2=auto + spectre_v2_user=auto + spec_store_bypass_disable=auto + l1tf=flush,nosmt + mds=full,nosmt + mminit_loglevel= [KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this parameter allows control of the logging verbosity for diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c index 9b8631533e02..be4266a57e54 100644 --- a/arch/powerpc/kernel/security.c +++ b/arch/powerpc/kernel/security.c @@ -57,7 +57,7 @@ void setup_barrier_nospec(void) enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR); - if (!no_nospec) + if (!no_nospec && cpu_spec_mitigations != CPU_SPEC_MITIGATIONS_OFF) enable_barrier_nospec(enable); } @@ -116,7 +116,7 @@ static int __init handle_nospectre_v2(char *p) early_param("nospectre_v2", handle_nospectre_v2); void setup_spectre_v2(void) { - if (no_spectrev2) + if (no_spectrev2 || cpu_spec_mitigations == CPU_SPEC_MITIGATIONS_OFF) do_btb_flush_fixups(); else btb_flush_enabled = true; @@ -307,7 +307,7 @@ void setup_stf_barrier(void) stf_enabled_flush_types = type; - if (!no_stf_barrier) + if (!no_stf_barrier && cpu_spec_mitigations != CPU_SPEC_MITIGATIONS_OFF) stf_barrier_enable(enable); } diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 236c1151a3a7..5fe43bcde325 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -958,7 +958,7 @@ void setup_rfi_flush(enum l1d_flush_type types, bool enable) enabled_flush_types = types; - if (!no_rfi_flush) + if (!no_rfi_flush || cpu_spec_mitigations != CPU_SPEC_MITIGATIONS_OFF) rfi_flush_enable(enable); } diff --git a/arch/s390/kernel/nospec-branch.c b/arch/s390/kernel/nospec-branch.c index bdddaae96559..c40eb672b43a 100644 --- a/arch/s390/kernel/nospec-branch.c +++ b/arch/s390/kernel/nospec-branch.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include <linux/module.h> #include <linux/device.h> +#include <linux/cpu.h> #include <asm/nospec-branch.h> static int __init nobp_setup_early(char *str) @@ -58,7 +59,8 @@ early_param("nospectre_v2", nospectre_v2_setup_early); void __init nospec_auto_detect(void) { - if (test_facility(156)) { + if (test_facility(156) || + cpu_spec_mitigations == CPU_SPEC_MITIGATIONS_OFF) { /* * The machine supports etokens. * Disable expolines and disable nobp. diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index aca1ef8cc79f..bb2ced3a491e 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -983,6 +983,7 @@ void microcode_check(void); enum l1tf_mitigations { L1TF_MITIGATION_OFF, + L1TF_MITIGATION_DEFAULT, L1TF_MITIGATION_FLUSH_NOWARN, L1TF_MITIGATION_FLUSH, L1TF_MITIGATION_FLUSH_NOSMT, @@ -994,6 +995,7 @@ extern enum l1tf_mitigations l1tf_mitigation; enum mds_mitigations { MDS_MITIGATION_OFF, + MDS_MITIGATION_DEFAULT, MDS_MITIGATION_FULL, MDS_MITIGATION_VMWERV, }; diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 346f0f05879d..7354daf3555f 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -222,7 +222,7 @@ static void x86_amd_ssb_disable(void) #define pr_fmt(fmt) "MDS: " fmt /* Default mitigation for L1TF-affected CPUs */ -static enum mds_mitigations mds_mitigation __ro_after_init = MDS_MITIGATION_FULL; +static enum mds_mitigations mds_mitigation __ro_after_init = MDS_MITIGATION_DEFAULT; static bool mds_nosmt __ro_after_init = false; static const char * const mds_strings[] = { @@ -238,6 +238,20 @@ static void mds_select_mitigation(void) return; } + if (mds_mitigation == MDS_MITIGATION_DEFAULT) { + switch (cpu_spec_mitigations) { + case CPU_SPEC_MITIGATIONS_OFF: + mds_mitigation = MDS_MITIGATION_OFF; + break; + case CPU_SPEC_MITIGATIONS_AUTO_NOSMT: + mds_nosmt = true; + /* fallthrough */ + case CPU_SPEC_MITIGATIONS_AUTO: + mds_mitigation = MDS_MITIGATION_FULL; + break; + } + } + if (mds_mitigation == MDS_MITIGATION_FULL) { if (!boot_cpu_has(X86_FEATURE_MD_CLEAR)) mds_mitigation = MDS_MITIGATION_VMWERV; @@ -374,8 +388,11 @@ spectre_v2_parse_user_cmdline(enum spectre_v2_mitigation_cmd v2_cmd) ret = cmdline_find_option(boot_command_line, "spectre_v2_user", arg, sizeof(arg)); - if (ret < 0) + if (ret < 0) { + if (cpu_spec_mitigations == CPU_SPEC_MITIGATIONS_OFF) + return SPECTRE_V2_USER_CMD_NONE; return SPECTRE_V2_USER_CMD_AUTO; + } for (i = 0; i < ARRAY_SIZE(v2_user_options); i++) { if (match_option(arg, ret, v2_user_options[i].option)) { @@ -510,8 +527,11 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void) return SPECTRE_V2_CMD_NONE; ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg)); - if (ret < 0) + if (ret < 0) { + if (cpu_spec_mitigations == CPU_SPEC_MITIGATIONS_OFF) + return SPECTRE_V2_CMD_NONE; return SPECTRE_V2_CMD_AUTO; + } for (i = 0; i < ARRAY_SIZE(mitigation_options); i++) { if (!match_option(arg, ret, mitigation_options[i].option)) @@ -716,9 +736,10 @@ void arch_smt_update(void) switch(mds_mitigation) { case MDS_MITIGATION_FULL: + case MDS_MITIGATION_DEFAULT: case MDS_MITIGATION_VMWERV: if (sched_smt_active() && !boot_cpu_has(X86_BUG_MSBDS_ONLY)) - pr_warn_once(MDS_MSG_SMT); + printk_once(KERN_WARNING MDS_MSG_SMT); update_mds_branch_idle(); break; case MDS_MITIGATION_OFF: @@ -771,8 +792,11 @@ static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void) } else { ret = cmdline_find_option(boot_command_line, "spec_store_bypass_disable", arg, sizeof(arg)); - if (ret < 0) + if (ret < 0) { + if (cpu_spec_mitigations == CPU_SPEC_MITIGATIONS_OFF) + return SPEC_STORE_BYPASS_CMD_NONE; return SPEC_STORE_BYPASS_CMD_AUTO; + } for (i = 0; i < ARRAY_SIZE(ssb_mitigation_options); i++) { if (!match_option(arg, ret, ssb_mitigation_options[i].option)) @@ -1037,7 +1061,7 @@ void x86_spec_ctrl_setup_ap(void) #define pr_fmt(fmt) "L1TF: " fmt /* Default mitigation for L1TF-affected CPUs */ -enum l1tf_mitigations l1tf_mitigation __ro_after_init = L1TF_MITIGATION_FLUSH; +enum l1tf_mitigations l1tf_mitigation __ro_after_init = L1TF_MITIGATION_DEFAULT; #if IS_ENABLED(CONFIG_KVM_INTEL) EXPORT_SYMBOL_GPL(l1tf_mitigation); #endif @@ -1092,8 +1116,23 @@ static void __init l1tf_select_mitigation(void) override_cache_bits(&boot_cpu_data); + if (l1tf_mitigation == L1TF_MITIGATION_DEFAULT) { + switch (cpu_spec_mitigations) { + case CPU_SPEC_MITIGATIONS_OFF: + l1tf_mitigation = L1TF_MITIGATION_OFF; + break; + case CPU_SPEC_MITIGATIONS_AUTO: + l1tf_mitigation = L1TF_MITIGATION_FLUSH; + break; + case CPU_SPEC_MITIGATIONS_AUTO_NOSMT: + l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOSMT; + break; + } + } + switch (l1tf_mitigation) { case L1TF_MITIGATION_OFF: + case L1TF_MITIGATION_DEFAULT: case L1TF_MITIGATION_FLUSH_NOWARN: case L1TF_MITIGATION_FLUSH: break; diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c index 4fee5c3003ed..943b641bc003 100644 --- a/arch/x86/mm/pti.c +++ b/arch/x86/mm/pti.c @@ -115,7 +115,8 @@ void __init pti_check_boottime_disable(void) } } - if (cmdline_find_option_bool(boot_command_line, "nopti")) { + if (cmdline_find_option_bool(boot_command_line, "nopti") || + cpu_spec_mitigations == CPU_SPEC_MITIGATIONS_OFF) { pti_mode = PTI_FORCE_OFF; pti_print_if_insecure("disabled on command line."); return; diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 3c87ad888ed3..6cdd3d5228d3 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -189,4 +189,12 @@ static inline void cpu_smt_disable(bool force) { } static inline void cpu_smt_check_topology(void) { } #endif +enum cpu_spec_mitigations { + CPU_SPEC_MITIGATIONS_OFF, + CPU_SPEC_MITIGATIONS_AUTO, + CPU_SPEC_MITIGATIONS_AUTO_NOSMT, +}; + +extern enum cpu_spec_mitigations cpu_spec_mitigations; + #endif /* _LINUX_CPU_H_ */ diff --git a/kernel/cpu.c b/kernel/cpu.c index d1c6d152da89..136d33fb90e5 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -2279,3 +2279,18 @@ void __init boot_cpu_hotplug_init(void) #endif this_cpu_write(cpuhp_state.state, CPUHP_ONLINE); } + +enum cpu_spec_mitigations cpu_spec_mitigations __ro_after_init = CPU_SPEC_MITIGATIONS_AUTO; + +static int __init cpu_spec_mitigations_setup(char *arg) +{ + if (!strcmp(arg, "off")) + cpu_spec_mitigations = CPU_SPEC_MITIGATIONS_OFF; + else if (!strcmp(arg, "auto")) + cpu_spec_mitigations = CPU_SPEC_MITIGATIONS_AUTO; + else if (!strcmp(arg, "auto,nosmt")) + cpu_spec_mitigations = CPU_SPEC_MITIGATIONS_AUTO_NOSMT; + + return 0; +} +early_param("cpu_spec_mitigations", cpu_spec_mitigations_setup); -- 2.17.2