[PATCH 3/4] x86: Enable User-Mode Instruction Prevention
From: Ricardo Neri
Date: Tue Nov 08 2016 - 01:13:32 EST
User_mode Instruction Prevention (UMIP) is enabled by setting/clearing a
bit in %cr4.
It make sense to enable UMIP at some point while booting, before user
spaces come up. Like SMAP and SMEP, is not critical to have it enabled
very early during boot. This is because UMIP is relevant only when there is
a userspace to be protected from. Given the similarities in relevance, it
makes sense to enable UMIP along with SMAP and SMEP.
Also, a __setup function is added to configure the enablement of UMIP with
kernel parameters. UMIP can be disabled completely or only for virtual-8086
tasks. We may want to disable UMIP for virtual-8086 tasks as there are
legitimate applications that utilize instructions disallowed by UMIP.
However, unconditionally disabling UMIP for virtual-8086 could be exploited
by malicious applications. Hence, we let the system owner to allow virtual-
8086 tasks to disable UMIP via a kernel parameter.
Rather than using the clearcpuid=1234 format for our kernel parameters,
this implementations relies on the format umip={no|novm86}. The intention
is to either disable UMIP completely or only for virtual-8086 tasks. The
format clearcpuid=1234 cannot take care of disabling UMIP for virtual-8086
tasks.
UMIP is enabled for all tasks by default; including virtual-8086 tasks.
Cc: Andy Lutomirski <luto@xxxxxxxxxx>
Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Cc: Borislav Petkov <bp@xxxxxxx>
Cc: Brian Gerst <brgerst@xxxxxxxxx>
Cc: Chen Yucong <slaoub@xxxxxxxxx>
Cc: Chris Metcalf <cmetcalf@xxxxxxxxxxxx>
Cc: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx>
Cc: Fenghua Yu <fenghua.yu@xxxxxxxxx>
Cc: Huang Rui <ray.huang@xxxxxxx>
Cc: Jiri Slaby <jslaby@xxxxxxx>
Cc: Jonathan Corbet <corbet@xxxxxxx>
Cc: Michael S. Tsirkin <mst@xxxxxxxxxx>
Cc: Paul Gortmaker <paul.gortmaker@xxxxxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Ravi V. Shankar <ravi.v.shankar@xxxxxxxxx>
Cc: Shuah Khan <shuah@xxxxxxxxxx>
Cc: Vlastimil Babka <vbabka@xxxxxxx>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@xxxxxxxxxxxxxxx>
---
Documentation/kernel-parameters.txt | 5 ++++
arch/x86/Kconfig | 10 ++++++++
arch/x86/kernel/cpu/common.c | 50 ++++++++++++++++++++++++++++++++++++-
3 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index fd5c052..95d0917 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -4201,6 +4201,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
Note that genuine overcurrent events won't be
reported either.
+ umip= [X86] Configure User-Mode Instruction Prevention
+ no = Disable UMIP even if it is supported by processor
+ novm86 = Disable UMIP only for virtual-8086 tasks; UMIP
+ remains active for all other tasks.
+
unknown_nmi_panic
[X86] Cause panic on unknown NMI.
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 770fb5f..dad93f9 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1718,6 +1718,16 @@ config X86_SMAP
If unsure, say Y.
+config X86_INTEL_UMIP
+ def_bool y
+ depends on CPU_SUP_INTEL
+ prompt "User Mode Instruction Prevention" if EXPERT
+ ---help---
+ The User Mode Instruction Prevention (UMIP) is a security
+ feature in newer Intel processors. If enabled, a general
+ protection fault is issued if the instructions SGDT, SLDT,
+ SIDT, SMSW and STR are executed in user mode.
+
config X86_INTEL_MPX
prompt "Intel MPX (Memory Protection Extensions)"
def_bool n
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index f3e7ab2..8f0e86c 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -44,6 +44,7 @@
#include <asm/pat.h>
#include <asm/microcode.h>
#include <asm/microcode_intel.h>
+#include <asm/vm86.h>
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/uv/uv.h>
@@ -306,6 +307,52 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c)
}
}
+static __init int setup_config_umip(char *arg)
+{
+ char info[] = "x86/umip: Intel User-Mode Execution Prevention (UMIP) disabled";
+ char error[] = "x86/umip: invalid kernel parameter. Valid parameters: umip=no";
+
+ /* do not emit a message if the feature is not present */
+ if (!boot_cpu_has(X86_FEATURE_UMIP))
+ return 1;
+
+ /* do not emit a message if the feature is not enabled */
+ if (!cpu_feature_enabled(X86_FEATURE_UMIP))
+ return 1;
+
+ if (parse_option_str(arg, "no")) {
+ setup_clear_cpu_cap(X86_FEATURE_UMIP);
+ pr_info("%s\n", info);
+ return 1;
+ }
+
+ if (IS_ENABLED(CONFIG_VM86) && parse_option_str(arg, "novm86")) {
+ vm86_disable_x86_umip();
+ pr_info("%s for vm86\n", info);
+ return 1;
+ }
+
+ if (IS_ENABLED(CONFIG_VM86))
+ pr_warn("%s, umip=novm86\n", error);
+ else
+ pr_warn("%s\n", error);
+ return 0;
+}
+__setup("umip=", setup_config_umip);
+
+static __always_inline void setup_umip(struct cpuinfo_x86 *c)
+{
+ if (cpu_feature_enabled(X86_FEATURE_UMIP) &&
+ cpu_has(c, X86_FEATURE_UMIP))
+ cr4_set_bits(X86_CR4_UMIP);
+ else
+ /*
+ * Make sure UMIP is disabled in case it was enabled in a
+ * previous boot (e.g., via kexec).
+ */
+ cr4_clear_bits(X86_CR4_UMIP);
+}
+
/*
* Protection Keys are not available in 32-bit mode.
*/
@@ -1037,9 +1084,10 @@ static void identify_cpu(struct cpuinfo_x86 *c)
/* Disable the PN if appropriate */
squash_the_stupid_serial_number(c);
- /* Set up SMEP/SMAP */
+ /* Set up SMEP/SMAP/UMIP */
setup_smep(c);
setup_smap(c);
+ setup_umip(c);
/*
* The vendor-specific functions might have changed features.
--
2.7.4