summaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorRicardo Neri <ricardo.neri-calderon@linux.intel.com>2017-11-13 22:29:44 -0800
committerIngo Molnar <mingo@kernel.org>2017-11-14 08:38:09 +0100
commit6e2a3064d6a86094fecc20cd430fd96aaa801687 (patch)
tree594c64d45e701ee83102b3b7324593492c0c2b84 /arch/x86
parent770c77557757873808a474016a3cae4b37690cb2 (diff)
downloadlinux-6e2a3064d6a86094fecc20cd430fd96aaa801687.tar.bz2
x86/umip: Identify the STR and SLDT instructions
The STR and SLDT instructions are not emulated by the UMIP code, thus there's no functionality in the decoder to identify them. However, a subsequent commit will introduce a warning about the use of all the instructions that UMIP protect/changes, not only those that are emulated. A first step for that is to add the ability to decode/identify them. Plus, now that STR and SLDT are identified, we need to explicitly avoid their emulation (i.e., not rely on successful identification). Group together all the cases that we do not want to emulate: STR, SLDT and user long mode processes. Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@suse.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi V. Shankar <ravi.v.shankar@intel.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Tony Luck <tony.luck@intel.com> Cc: ricardo.neri@intel.com Link: http://lkml.kernel.org/r/1510640985-18412-4-git-send-email-ricardo.neri-calderon@linux.intel.com [ Rewrote the changelog, fixed ugly col80 artifact. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/umip.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index 6ba82be68cff..1f1f2d54dab5 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -78,7 +78,9 @@
#define UMIP_INST_SGDT 0 /* 0F 01 /0 */
#define UMIP_INST_SIDT 1 /* 0F 01 /1 */
-#define UMIP_INST_SMSW 3 /* 0F 01 /4 */
+#define UMIP_INST_SMSW 2 /* 0F 01 /4 */
+#define UMIP_INST_SLDT 3 /* 0F 00 /0 */
+#define UMIP_INST_STR 4 /* 0F 00 /1 */
/**
* identify_insn() - Identify a UMIP-protected instruction
@@ -118,10 +120,16 @@ static int identify_insn(struct insn *insn)
default:
return -EINVAL;
}
+ } else if (insn->opcode.bytes[1] == 0x0) {
+ if (X86_MODRM_REG(insn->modrm.value) == 0)
+ return UMIP_INST_SLDT;
+ else if (X86_MODRM_REG(insn->modrm.value) == 1)
+ return UMIP_INST_STR;
+ else
+ return -EINVAL;
+ } else {
+ return -EINVAL;
}
-
- /* SLDT AND STR are not emulated */
- return -EINVAL;
}
/**
@@ -267,10 +275,6 @@ bool fixup_umip_exception(struct pt_regs *regs)
if (!regs)
return false;
- /* Do not emulate 64-bit processes. */
- if (user_64bit_mode(regs))
- return false;
-
/*
* If not in user-space long mode, a custom code segment could be in
* use. This is true in protected mode (if the process defined a local
@@ -322,6 +326,10 @@ bool fixup_umip_exception(struct pt_regs *regs)
if (umip_inst < 0)
return false;
+ /* Do not emulate SLDT, STR or user long mode processes. */
+ if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT || user_64bit_mode(regs))
+ return false;
+
if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size))
return false;