Commit de5397ad5b9ad22e2401c4dacdf1bb3b19c05679

Authored by Fenghua Yu
Committed by H. Peter Anvin
1 parent dc23c0bccf

x86, cpu: Enable/disable Supervisor Mode Execution Protection

Enable/disable newly documented SMEP (Supervisor Mode Execution Protection) CPU
feature in kernel. CR4.SMEP (bit 20) is 0 at power-on. If the feature is
supported by CPU (X86_FEATURE_SMEP), enable SMEP by setting CR4.SMEP. New kernel
option nosmep disables the feature even if the feature is supported by CPU.

[ hpa: moved the call to setup_smep() until after the vendor-specific
  initialization; that ensures that CPUID features are unmasked.  We
  will still run it before we have userspace (never mind uncontrolled
  userspace). ]

Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
LKML-Reference: <1305157865-31727-1-git-send-email-fenghua.yu@intel.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>

Showing 2 changed files with 27 additions and 0 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -1664,6 +1664,10 @@
1664 1664 noexec=on: enable non-executable mappings (default)
1665 1665 noexec=off: disable non-executable mappings
1666 1666  
  1667 + nosmep [X86]
  1668 + Disable SMEP (Supervisor Mode Execution Protection)
  1669 + even if it is supported by processor.
  1670 +
1667 1671 noexec32 [X86-64]
1668 1672 This affects only 32-bit executables.
1669 1673 noexec32=on: enable non-executable mappings (default)
arch/x86/kernel/cpu/common.c
... ... @@ -254,6 +254,25 @@
254 254 }
255 255 #endif
256 256  
  257 +static int disable_smep __initdata;
  258 +static __init int setup_disable_smep(char *arg)
  259 +{
  260 + disable_smep = 1;
  261 + return 1;
  262 +}
  263 +__setup("nosmep", setup_disable_smep);
  264 +
  265 +static __init void setup_smep(struct cpuinfo_x86 *c)
  266 +{
  267 + if (cpu_has(c, X86_FEATURE_SMEP)) {
  268 + if (unlikely(disable_smep)) {
  269 + setup_clear_cpu_cap(X86_FEATURE_SMEP);
  270 + clear_in_cr4(X86_CR4_SMEP);
  271 + } else
  272 + set_in_cr4(X86_CR4_SMEP);
  273 + }
  274 +}
  275 +
257 276 /*
258 277 * Some CPU features depend on higher CPUID levels, which may not always
259 278 * be available due to CPUID level capping or broken virtualization
... ... @@ -667,6 +686,8 @@
667 686 c->cpu_index = 0;
668 687 #endif
669 688 filter_cpuid_features(c, false);
  689 +
  690 + setup_smep(c);
670 691 }
671 692  
672 693 void __init early_cpu_init(void)
... ... @@ -751,6 +772,8 @@
751 772 c->phys_proc_id = c->initial_apicid;
752 773 #endif
753 774 }
  775 +
  776 + setup_smep(c);
754 777  
755 778 get_model_name(c); /* Default name */
756 779