diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ad7e2e5088c126ce48e0362d1f3296f3e8b55d2b..49c5c41b07e1d1a21327f51d16f950045a5e1b66 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1812,8 +1812,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. noexec=on: enable non-executable mappings (default) noexec=off: disable non-executable mappings + nosmap [X86] + Disable SMAP (Supervisor Mode Access Prevention) + even if it is supported by processor. + nosmep [X86] - Disable SMEP (Supervisor Mode Execution Protection) + Disable SMEP (Supervisor Mode Execution Prevention) even if it is supported by processor. noexec32 [X86-64] diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index cd43e525fde8e9309f773ce9675fb5b0107ebebe..7d35d65941181d4c5db49293ff4f49448451c638 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -278,6 +278,31 @@ static __cpuinit void setup_smep(struct cpuinfo_x86 *c) } } +static int disable_smap __cpuinitdata; +static __init int setup_disable_smap(char *arg) +{ + disable_smap = 1; + return 1; +} +__setup("nosmap", setup_disable_smap); + +static __cpuinit void setup_smap(struct cpuinfo_x86 *c) +{ + if (cpu_has(c, X86_FEATURE_SMAP)) { + if (unlikely(disable_smap)) { + setup_clear_cpu_cap(X86_FEATURE_SMAP); + clear_in_cr4(X86_CR4_SMAP); + } else { + set_in_cr4(X86_CR4_SMAP); + /* + * Don't use clac() here since alternatives + * haven't run yet... + */ + asm volatile(__stringify(__ASM_CLAC) ::: "memory"); + } + } +} + /* * Some CPU features depend on higher CPUID levels, which may not always * be available due to CPUID level capping or broken virtualization @@ -713,6 +738,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) filter_cpuid_features(c, false); setup_smep(c); + setup_smap(c); if (this_cpu->c_bsp_init) this_cpu->c_bsp_init(c);