All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention
@ 2017-11-06  2:27 Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 01/12] x86/insn-eval: Compute linear address in several utility functions Ricardo Neri
                   ` (12 more replies)
  0 siblings, 13 replies; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri

This the 11th revision of a patchset to enable User-Mode Instruction
Prevention (UMIP) in Linux. This is the second part of two series. After
having completed review, the first series [1] has been merged in the tip
tree. v10 of this series can be found here [2].

In this series, support is added to handle 32-bit and 16-bit addresses in
protected and virtual-8086 modes plus effectively enabling UMIP. See below
for a description on why this support is needed.

=== What is UMIP?

User-Mode Instruction Prevention (UMIP) is a security feature present in
new Intel Processors. If enabled, it prevents the execution of certain
instructions if the Current Privilege Level (CPL) is greater than 0. If
these instructions were executed while in CPL > 0, user space applications
could have access to system-wide settings such as the global and local
descriptor tables, the segment selectors to the current task state and the
local descriptor table. Hiding these system resources reduces the tools
available to craft privilege escalation attacks such as [3].

These are the instructions covered by UMIP:
* SGDT - Store Global Descriptor Table
* SIDT - Store Interrupt Descriptor Table
* SLDT - Store Local Descriptor Table
* SMSW - Store Machine Status Word
* STR - Store Task Register

If any of these instructions is executed with CPL > 0, a general protection
exception is issued when UMIP is enabled. This means that any process that
attempts to use the aforementioned instructions would see a SIGSEGV signal.

=== How does it impact applications?

When enabled, however, UMIP will change the behavior that certain
applications expect from the operating system. For instance, programs
running on WineHQ and DOSEMU2 rely on some of these instructions to
function. Stas Sergeev found that Microsoft Windows 3.1 and dos4gw use the
instruction SMSW when running in virtual-8086 mode [4]. SGDT and SIDT can
also be used on virtual-8086 mode.

In order to not change the behavior of the system (i.e., a SIGSEGV signal
should not be generated when using these instructions), this implementation
traps the #GP fault generated by the CPU and emulates SGDT, SIDT and SMSW.
with dummy returned values. This should be sufficient to not break the
applications mentioned above. Regarding the two remaining instructions,
STR and SLDT, the WineHQ team has shown interest catching the general
protection fault and use it as a vehicle to fix broken applications[5].

Thus, emulation is only provided for protected and virtual-8086 modes. No
emulation is implemented for processes running in long mode. Also the
instructions SLDT and STR are not emulated in any case.

DOSEMU2 emulates virtual-8086 mode via KVM. No applications will be broken
unless DOSEMU2 decides to enable the CR4.UMIP bit in platforms that support
it. Also, this should not pose a security risk as no system resources would
be revealed. Instead, code running inside the KVM would only see the KVM's
GDT, IDT and MSW.

=== How is this series laid out?

++ Extend the insn-eval library
This library is extended to also support 32-bit and 16 bit addresses. This
also implies to add functionality to enforce segment limits in protected
mode and linear address sizes in virtual-8086 mode as described in the
section 20.1.1 of the Intel 64 and IA-32 Architectures Software Development
Manual Vol. 3.

++ Emulate UMIP instructions
A new fixup_umip_exception() functions inspect the instruction at the
instruction pointer. If it is an UMIP-protected instruction, it executes
the emulation code.

++ Add self-tests
Lastly, self-tests are added to entry_from_v86.c to exercise the most
typical use cases of UMIP-protected instructions in a virtual-8086 mode.

++ Extensive tests
Extensive tests were performed to test all the combinations of ModRM,
SiB and displacements for 16-bit and 32-bit encodings for the SS, DS,
ES, FS and GS segments. Tests also include a 64-bit program that uses
segmentation via FS and GS. For this purpose, I temporarily enabled UMIP
support for 64-bit process. This change is not part of this patchset.
The intention is to test the computations of linear addresses in 64-bit
mode, including the extra R8-R15 registers. Extensive test is also
implemented for virtual-8086 tasks. Code of these tests can be found here
[6] and here [7].

Thanks and BR,
Ricardo

[1]. https://www.spinics.net/lists/kernel/msg2635138.html
[2]. https://lkml.org/lkml/2017/10/27/699
[3]. http://timetobleed.com/a-closer-look-at-a-recent-privilege-escalation-bug-in-linux-cve-2013-2094/
[4]. https://www.winehq.org/pipermail/wine-devel/2017-April/117159.html
[5]. https://marc.info/?l=linux-kernel&m=147876798717927&w=2
[6]. https://github.com/01org/luv-yocto/tree/rneri/umip/meta-luv/recipes-core/umip/files
[7]. https://github.com/01org/luv-yocto/commit/a72a7fe7d68693c0f4100ad86de6ecabde57334f#diff-3860c136a63add269bce4ea50222c248R1

Changes since V10:
*Patch 1 ("x86/insn-eval: Extend get_seg_base_addr() to also obtain segment
 limit") of v10 has been dropped has it has been merged in the tip tree.
*Removed unnecessary wrap-around of function calls to enforce the 80
 chars-per-line rule. In some cases, variables were renamed.
*Removed unnecessary casts between variables of the same width.
*Reworked casts between variables of different width in favor of bit
 masks. Casts were kept for arithmetic operations.
*Reworded patch descriptions and documentation of several functions to
 improve clarity.

Changes since V9:
*All the changes described in [1], plus:
*Created new utility functions utility functions to handle each x86
 memory addressing mode separately. Also, such functions are extended to
 support 32-bit addresses. A separate set of function is used for 16-bit
 addresses.
*Extended and rename the function get_seg_base_addr() as
 get_seg_base_addr() to also return the limit of the segment associated
 with the instruction operand.

Ricardo Neri (12):
  x86/insn-eval: Compute linear address in several utility functions
  x86/insn-eval: Add support to resolve 32-bit address encodings
  x86/insn-eval: Add wrapper function for 32 and 64-bit addresses
  x86/insn-eval: Handle 32-bit address encodings in virtual-8086 mode
  x86/insn-eval: Add support to resolve 16-bit address encodings
  x86/cpufeature: Add User-Mode Instruction Prevention definitions
  x86: Add emulation code for UMIP instructions
  x86/umip: Force a page fault when unable to copy emulated result to
    user
  x86: Enable User-Mode Instruction Prevention at runtime
  x86/traps: Fixup general protection faults caused by UMIP
  selftests/x86: Add tests for User-Mode Instruction Prevention
  selftests/x86: Add tests for instruction str and sldt

 arch/x86/Kconfig                              |  10 +
 arch/x86/include/asm/cpufeatures.h            |   1 +
 arch/x86/include/asm/disabled-features.h      |   8 +-
 arch/x86/include/asm/umip.h                   |  12 +
 arch/x86/include/uapi/asm/processor-flags.h   |   2 +
 arch/x86/kernel/Makefile                      |   1 +
 arch/x86/kernel/cpu/common.c                  |  25 +-
 arch/x86/kernel/traps.c                       |   5 +
 arch/x86/kernel/umip.c                        | 366 ++++++++++++++++
 arch/x86/lib/insn-eval.c                      | 609 +++++++++++++++++++++++---
 tools/testing/selftests/x86/entry_from_vm86.c |  89 +++-
 11 files changed, 1070 insertions(+), 58 deletions(-)
 create mode 100644 arch/x86/include/asm/umip.h
 create mode 100644 arch/x86/kernel/umip.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v11 01/12] x86/insn-eval: Compute linear address in several utility functions
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08 10:57   ` [tip:x86/asm] " tip-bot for Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 02/12] x86/insn-eval: Add support to resolve 32-bit address encodings Ricardo Neri
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Adam Buchbinder, Colin Ian King, Lorenzo Stoakes, Qiaowei Ren,
	Arnaldo Carvalho de Melo, Adrian Hunter, Kees Cook,
	Thomas Garnier, Dmitry Vyukov

Computing a linear address involves several steps. The first step is to
compute the effective address. This requires determining the addressing
mode in use and perform arithmetic operations on the operands. Plus, each
addressing mode has special cases that must be handled.

Once the effective address is known, the base address of the applicable
segment is added to obtain the linear address.

Clearly, this is too much work for a single function. Instead, handle each
addressing mode in a separate utility function. This improves readability
and gives us the opportunity to handler errors better.

At the moment, arithmetic to compute the effective address uses 64-byte
variables. Thus, limit support to 64-bit addresses.

While reworking the function insn_get_addr_ref(), the variable addr_offset
is renamed as regoff to reflect its actual use (i.e., offset, from the
base of pt_regs, of the register used as operand).

Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Colin Ian King <colin.king@canonical.com>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: x86@kernel.org
Suggested-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 arch/x86/lib/insn-eval.c | 243 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 185 insertions(+), 58 deletions(-)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index 91f08aa..a4427b4 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -776,6 +776,182 @@ static int get_seg_base_limit(struct insn *insn, struct pt_regs *regs,
 	return 0;
 }
 
+/**
+ * get_eff_addr_reg() - Obtain effective address from register operand
+ * @insn:	Instruction. Must be valid.
+ * @regs:	Register values as seen when entering kernel mode
+ * @regoff:	Obtained operand offset, in pt_regs, with the effective address
+ * @eff_addr:	Obtained effective address
+ *
+ * Obtain the effective address stored in the register operand as indicated by
+ * the ModRM byte. This function is to be used only with register addressing
+ * (i.e.,  ModRM.mod is 3). The effective address is saved in @eff_addr. The
+ * register operand, as an offset from the base of pt_regs, is saved in @regoff;
+ * such offset can then be used to resolve the segment associated with the
+ * operand. This function can be used with any of the supported address sizes
+ * in x86.
+ *
+ * Returns:
+ *
+ * 0 on success. @eff_addr will have the effective address stored in the
+ * operand indicated by ModRM. @regoff will have such operand as an offset from
+ * the base of pt_regs.
+ *
+ * -EINVAL on error.
+ */
+static int get_eff_addr_reg(struct insn *insn, struct pt_regs *regs,
+			    int *regoff, long *eff_addr)
+{
+	insn_get_modrm(insn);
+
+	if (!insn->modrm.nbytes)
+		return -EINVAL;
+
+	if (X86_MODRM_MOD(insn->modrm.value) != 3)
+		return -EINVAL;
+
+	*regoff = get_reg_offset(insn, regs, REG_TYPE_RM);
+	if (*regoff < 0)
+		return -EINVAL;
+
+	*eff_addr = regs_get_register(regs, *regoff);
+
+	return 0;
+}
+
+/**
+ * get_eff_addr_modrm() - Obtain referenced effective address via ModRM
+ * @insn:	Instruction. Must be valid.
+ * @regs:	Register values as seen when entering kernel mode
+ * @regoff:	Obtained operand offset, in pt_regs, associated with segment
+ * @eff_addr:	Obtained effective address
+ *
+ * Obtain the effective address referenced by the ModRM byte of @insn. After
+ * identifying the registers involved in the register-indirect memory reference,
+ * its value is obtained from the operands in @regs. The computed address is
+ * stored @eff_addr. Also, the register operand that indicates the associated
+ * segment is stored in @regoff, this parameter can later be used to determine
+ * such segment.
+ *
+ * Returns:
+ *
+ * 0 on success. @eff_addr will have the referenced effective address. @regoff
+ * will have a register, as an offset from the base of pt_regs, that can be used
+ * to resolve the associated segment.
+ *
+ * -EINVAL on error.
+ */
+static int get_eff_addr_modrm(struct insn *insn, struct pt_regs *regs,
+			      int *regoff, long *eff_addr)
+{
+	long tmp;
+
+	if (insn->addr_bytes != 8)
+		return -EINVAL;
+
+	insn_get_modrm(insn);
+
+	if (!insn->modrm.nbytes)
+		return -EINVAL;
+
+	if (X86_MODRM_MOD(insn->modrm.value) > 2)
+		return -EINVAL;
+
+	*regoff = get_reg_offset(insn, regs, REG_TYPE_RM);
+
+	/*
+	 * -EDOM means that we must ignore the address_offset. In such a case,
+	 * in 64-bit mode the effective address relative to the rIP of the
+	 * following instruction.
+	 */
+	if (*regoff == -EDOM) {
+		if (user_64bit_mode(regs))
+			tmp = regs->ip + insn->length;
+		else
+			tmp = 0;
+	} else if (*regoff < 0) {
+		return -EINVAL;
+	} else {
+		tmp = regs_get_register(regs, *regoff);
+	}
+
+	*eff_addr = tmp + insn->displacement.value;
+
+	return 0;
+}
+
+/**
+ * get_eff_addr_sib() - Obtain referenced effective address via SIB
+ * @insn:	Instruction. Must be valid.
+ * @regs:	Register values as seen when entering kernel mode
+ * @regoff:	Obtained operand offset, in pt_regs, associated with segment
+ * @eff_addr:	Obtained effective address
+ *
+ * Obtain the effective address referenced by the SIB byte of @insn. After
+ * identifying the registers involved in the indexed, register-indirect memory
+ * reference, its value is obtained from the operands in @regs. The computed
+ * address is stored @eff_addr. Also, the register operand that indicates the
+ * associated segment is stored in @regoff, this parameter can later be used to
+ * determine such segment.
+ *
+ * Returns:
+ *
+ * 0 on success. @eff_addr will have the referenced effective address.
+ * @base_offset will have a register, as an offset from the base of pt_regs,
+ * that can be used to resolve the associated segment.
+ *
+ * -EINVAL on error.
+ */
+static int get_eff_addr_sib(struct insn *insn, struct pt_regs *regs,
+			    int *base_offset, long *eff_addr)
+{
+	long base, indx;
+	int indx_offset;
+
+	if (insn->addr_bytes != 8)
+		return -EINVAL;
+
+	insn_get_modrm(insn);
+
+	if (!insn->modrm.nbytes)
+		return -EINVAL;
+
+	if (X86_MODRM_MOD(insn->modrm.value) > 2)
+		return -EINVAL;
+
+	insn_get_sib(insn);
+
+	if (!insn->sib.nbytes)
+		return -EINVAL;
+
+	*base_offset = get_reg_offset(insn, regs, REG_TYPE_BASE);
+	indx_offset = get_reg_offset(insn, regs, REG_TYPE_INDEX);
+
+	/*
+	 * Negative values in the base and index offset means an error when
+	 * decoding the SIB byte. Except -EDOM, which means that the registers
+	 * should not be used in the address computation.
+	 */
+	if (*base_offset == -EDOM)
+		base = 0;
+	else if (*base_offset < 0)
+		return -EINVAL;
+	else
+		base = regs_get_register(regs, *base_offset);
+
+	if (indx_offset == -EDOM)
+		indx = 0;
+	else if (indx_offset < 0)
+		return -EINVAL;
+	else
+		indx = regs_get_register(regs, indx_offset);
+
+	*eff_addr = base + indx * (1 << X86_SIB_SCALE(insn->sib.value));
+
+	*eff_addr += insn->displacement.value;
+
+	return 0;
+}
 /*
  * return the address being referenced be instruction
  * for rm=3 returning the content of the rm reg
@@ -783,78 +959,29 @@ static int get_seg_base_limit(struct insn *insn, struct pt_regs *regs,
  */
 void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 {
-	int addr_offset, base_offset, indx_offset, ret;
 	unsigned long linear_addr = -1L, seg_base;
-	long eff_addr, base, indx;
-	insn_byte_t sib;
-
-	insn_get_modrm(insn);
-	insn_get_sib(insn);
-	sib = insn->sib.value;
+	int regoff, ret;
+	long eff_addr;
 
 	if (X86_MODRM_MOD(insn->modrm.value) == 3) {
-		addr_offset = get_reg_offset(insn, regs, REG_TYPE_RM);
-		if (addr_offset < 0)
+		ret = get_eff_addr_reg(insn, regs, &regoff, &eff_addr);
+		if (ret)
 			goto out;
 
-		eff_addr = regs_get_register(regs, addr_offset);
-
 	} else {
 		if (insn->sib.nbytes) {
-			/*
-			 * Negative values in the base and index offset means
-			 * an error when decoding the SIB byte. Except -EDOM,
-			 * which means that the registers should not be used
-			 * in the address computation.
-			 */
-			base_offset = get_reg_offset(insn, regs, REG_TYPE_BASE);
-			if (base_offset == -EDOM)
-				base = 0;
-			else if (base_offset < 0)
+			ret = get_eff_addr_sib(insn, regs, &regoff, &eff_addr);
+			if (ret)
 				goto out;
-			else
-				base = regs_get_register(regs, base_offset);
-
-			indx_offset = get_reg_offset(insn, regs, REG_TYPE_INDEX);
-
-			if (indx_offset == -EDOM)
-				indx = 0;
-			else if (indx_offset < 0)
-				goto out;
-			else
-				indx = regs_get_register(regs, indx_offset);
-
-			eff_addr = base + indx * (1 << X86_SIB_SCALE(sib));
-
-			/*
-			 * The base determines the segment used to compute
-			 * the linear address.
-			 */
-			addr_offset = base_offset;
-
 		} else {
-			addr_offset = get_reg_offset(insn, regs, REG_TYPE_RM);
-			/*
-			 * -EDOM means that we must ignore the address_offset.
-			 * In such a case, in 64-bit mode the effective address
-			 * relative to the RIP of the following instruction.
-			 */
-			if (addr_offset == -EDOM) {
-				if (user_64bit_mode(regs))
-					eff_addr = (long)regs->ip + insn->length;
-				else
-					eff_addr = 0;
-			} else if (addr_offset < 0) {
+			ret = get_eff_addr_modrm(insn, regs, &regoff, &eff_addr);
+			if (ret)
 				goto out;
-			} else {
-				eff_addr = regs_get_register(regs, addr_offset);
-			}
 		}
 
-		eff_addr += insn->displacement.value;
 	}
 
-	ret = get_seg_base_limit(insn, regs, addr_offset, &seg_base, NULL);
+	ret = get_seg_base_limit(insn, regs, regoff, &seg_base, NULL);
 	if (ret)
 		goto out;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v11 02/12] x86/insn-eval: Add support to resolve 32-bit address encodings
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 01/12] x86/insn-eval: Compute linear address in several utility functions Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08 10:58   ` [tip:x86/asm] " tip-bot for Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 03/12] x86/insn-eval: Add wrapper function for 32 and 64-bit addresses Ricardo Neri
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Adam Buchbinder, Colin Ian King, Lorenzo Stoakes, Qiaowei Ren,
	Arnaldo Carvalho de Melo, Adrian Hunter, Kees Cook,
	Thomas Garnier, Dmitry Vyukov

32-bit and 64-bit address encodings are identical. Thus, the same logic
could be used to resolve the effective address. However, there are two key
differences: address size and enforcement of segment limits.

If running a 32-bit process on a 64-bit kernel, it is best to perform
the address calculation using 32-bit data types. In this manner hardware
is used for the arithmetic, including handling of signs and overflows.

32-bit addresses are generally used in protected mode; segment limits are
enforced in this mode. This implementation obtains the limit of the
segment associated with the instruction operands and prefixes. If the
computed address is outside the segment limits, an error is returned. It
is also possible to use 32-bit address in long mode and virtual-8086 mode
by using an address override prefix. In such cases, segment limits are not
enforced.

Support to use 32-bit arithmetic is added to the utility functions that
compute effective addresses. However, the end result is stored in a
variable of type long (which has a width of 8 bytes in 64-bit builds).
Hence, once a 32-bit effective address is computed, the 4 most significant
bytes are masked out to avoid sign extension.

The newly added function get_addr_ref_32() is almost identical to the
existing function insn_get_addr_ref() (used for 64-bit addresses). The only
difference is that it verifies that the effective address is within the
limits of the segment.

Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Colin Ian King <colin.king@canonical.com>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: x86@kernel.org
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 arch/x86/lib/insn-eval.c | 112 ++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 106 insertions(+), 6 deletions(-)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index a4427b4..e6cb68a 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -814,7 +814,11 @@ static int get_eff_addr_reg(struct insn *insn, struct pt_regs *regs,
 	if (*regoff < 0)
 		return -EINVAL;
 
-	*eff_addr = regs_get_register(regs, *regoff);
+	/* Ignore bytes that are outside the address size. */
+	if (insn->addr_bytes == 4)
+		*eff_addr = regs_get_register(regs, *regoff) & 0xffffffff;
+	else /* 64-bit address */
+		*eff_addr = regs_get_register(regs, *regoff);
 
 	return 0;
 }
@@ -846,7 +850,7 @@ static int get_eff_addr_modrm(struct insn *insn, struct pt_regs *regs,
 {
 	long tmp;
 
-	if (insn->addr_bytes != 8)
+	if (insn->addr_bytes != 8 && insn->addr_bytes != 4)
 		return -EINVAL;
 
 	insn_get_modrm(insn);
@@ -875,7 +879,13 @@ static int get_eff_addr_modrm(struct insn *insn, struct pt_regs *regs,
 		tmp = regs_get_register(regs, *regoff);
 	}
 
-	*eff_addr = tmp + insn->displacement.value;
+	if (insn->addr_bytes == 4) {
+		int addr32 = (int)(tmp & 0xffffffff) + insn->displacement.value;
+
+		*eff_addr = addr32 & 0xffffffff;
+	} else {
+		*eff_addr = tmp + insn->displacement.value;
+	}
 
 	return 0;
 }
@@ -908,7 +918,7 @@ static int get_eff_addr_sib(struct insn *insn, struct pt_regs *regs,
 	long base, indx;
 	int indx_offset;
 
-	if (insn->addr_bytes != 8)
+	if (insn->addr_bytes != 8 && insn->addr_bytes != 4)
 		return -EINVAL;
 
 	insn_get_modrm(insn);
@@ -946,12 +956,102 @@ static int get_eff_addr_sib(struct insn *insn, struct pt_regs *regs,
 	else
 		indx = regs_get_register(regs, indx_offset);
 
-	*eff_addr = base + indx * (1 << X86_SIB_SCALE(insn->sib.value));
+	if (insn->addr_bytes == 4) {
+		int addr32, base32, idx32;
+
+		base32 = base & 0xffffffff;
+		idx32 = indx & 0xffffffff;
 
-	*eff_addr += insn->displacement.value;
+		addr32 = base32 + idx32 * (1 << X86_SIB_SCALE(insn->sib.value));
+		addr32 += insn->displacement.value;
+
+		*eff_addr = addr32 & 0xffffffff;
+	} else {
+		*eff_addr = base + indx * (1 << X86_SIB_SCALE(insn->sib.value));
+		*eff_addr += insn->displacement.value;
+	}
 
 	return 0;
 }
+
+/**
+ * get_addr_ref_32() - Obtain a 32-bit linear address
+ * @insn:	Instruction with ModRM, SIB bytes and displacement
+ * @regs:	Register values as seen when entering kernel mode
+ *
+ * This function is to be used with 32-bit address encodings to obtain the
+ * linear memory address referred by the instruction's ModRM, SIB,
+ * displacement bytes and segment base address, as applicable. If in protected
+ * mode, segment limits are enforced.
+ *
+ * Returns:
+ *
+ * Linear address referenced by instruction and registers on success.
+ *
+ * -1L on error.
+ */
+static void __user *get_addr_ref_32(struct insn *insn, struct pt_regs *regs)
+{
+	unsigned long linear_addr = -1L, seg_base, seg_limit;
+	int eff_addr, regoff;
+	long tmp;
+	int ret;
+
+	if (insn->addr_bytes != 4)
+		goto out;
+
+	if (X86_MODRM_MOD(insn->modrm.value) == 3) {
+		ret = get_eff_addr_reg(insn, regs, &regoff, &tmp);
+		if (ret)
+			goto out;
+
+		eff_addr = tmp;
+
+	} else {
+		if (insn->sib.nbytes) {
+			ret = get_eff_addr_sib(insn, regs, &regoff, &tmp);
+			if (ret)
+				goto out;
+
+			eff_addr = tmp;
+		} else {
+			ret = get_eff_addr_modrm(insn, regs, &regoff, &tmp);
+			if (ret)
+				goto out;
+
+			eff_addr = tmp;
+		}
+	}
+
+	ret = get_seg_base_limit(insn, regs, regoff, &seg_base, &seg_limit);
+	if (ret)
+		goto out;
+
+	/*
+	 * In protected mode, before computing the linear address, make sure
+	 * the effective address is within the limits of the segment.
+	 * 32-bit addresses can be used in long and virtual-8086 modes if an
+	 * address override prefix is used. In such cases, segment limits are
+	 * not enforced. When in virtual-8086 mode, the segment limit is -1L
+	 * to reflect this situation.
+	 *
+	 * After computed, the effective address is treated as an unsigned
+	 * quantity.
+	 */
+	if (!user_64bit_mode(regs) && ((unsigned int)eff_addr > seg_limit))
+		goto out;
+
+	/*
+	 * Data type long could be 64 bits in size. Ensure that our 32-bit
+	 * effective address is not sign-extended when computing the linear
+	 * address.
+	 */
+	linear_addr = (unsigned long)(eff_addr & 0xffffffff) + seg_base;
+
+out:
+	return (void __user *)linear_addr;
+}
+
 /*
  * return the address being referenced be instruction
  * for rm=3 returning the content of the rm reg
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v11 03/12] x86/insn-eval: Add wrapper function for 32 and 64-bit addresses
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 01/12] x86/insn-eval: Compute linear address in several utility functions Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 02/12] x86/insn-eval: Add support to resolve 32-bit address encodings Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08 10:58   ` [tip:x86/asm] " tip-bot for Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 04/12] x86/insn-eval: Handle 32-bit address encodings in virtual-8086 mode Ricardo Neri
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Adam Buchbinder, Colin Ian King, Lorenzo Stoakes, Qiaowei Ren,
	Arnaldo Carvalho de Melo, Adrian Hunter, Kees Cook,
	Thomas Garnier, Dmitry Vyukov

The function insn_get_addr_ref() is capable of handling only 64-bit
addresses. A previous commit introduced a function to handle 32-bit
addresses. Invoke these two functions from a third wrapper function that
calls the appropriate routine based on the address size specified in the
instruction structure (obtained by looking at the code segment default
address size and the address override prefix, if present).

While doing this, rename the original function insn_get_addr_ref() with
the more appropriate name get_addr_ref_64(), ensure it is only used
for 64-bit addresses.

Also, since 64-bit addresses are not possible in 32-bit builds, provide
a dummy function such case.

Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Colin Ian King <colin.king@canonical.com>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: x86@kernel.org
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 arch/x86/lib/insn-eval.c | 60 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 55 insertions(+), 5 deletions(-)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index e6cb68a..1ac3973 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -1052,17 +1052,36 @@ static void __user *get_addr_ref_32(struct insn *insn, struct pt_regs *regs)
 	return (void __user *)linear_addr;
 }
 
-/*
- * return the address being referenced be instruction
- * for rm=3 returning the content of the rm reg
- * for rm!=3 calculates the address using SIB and Disp
+/**
+ * get_addr_ref_64() - Obtain a 64-bit linear address
+ * @insn:	Instruction struct with ModRM and SIB bytes and displacement
+ * @regs:	Structure with register values as seen when entering kernel mode
+ *
+ * This function is to be used with 64-bit address encodings to obtain the
+ * linear memory address referred by the instruction's ModRM, SIB,
+ * displacement bytes and segment base address, as applicable.
+ *
+ * Returns:
+ *
+ * Linear address referenced by instruction and registers on success.
+ *
+ * -1L on error.
  */
-void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
+#ifndef CONFIG_X86_64
+static void __user *get_addr_ref_64(struct insn *insn, struct pt_regs *regs)
+{
+	return (void __user *)-1L;
+}
+#else
+static void __user *get_addr_ref_64(struct insn *insn, struct pt_regs *regs)
 {
 	unsigned long linear_addr = -1L, seg_base;
 	int regoff, ret;
 	long eff_addr;
 
+	if (insn->addr_bytes != 8)
+		goto out;
+
 	if (X86_MODRM_MOD(insn->modrm.value) == 3) {
 		ret = get_eff_addr_reg(insn, regs, &regoff, &eff_addr);
 		if (ret)
@@ -1090,3 +1109,34 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 out:
 	return (void __user *)linear_addr;
 }
+#endif /* CONFIG_X86_64 */
+
+/**
+ * insn_get_addr_ref() - Obtain the linear address referred by instruction
+ * @insn:	Instruction structure containing ModRM byte and displacement
+ * @regs:	Structure with register values as seen when entering kernel mode
+ *
+ * Obtain the linear address referred by the instruction's ModRM, SIB and
+ * displacement bytes, and segment base, as applicable. In protected mode,
+ * segment limits are enforced.
+ *
+ * Returns:
+ *
+ * Linear address referenced by instruction and registers on success.
+ *
+ * -1L on error.
+ */
+void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
+{
+	if (!insn || !regs)
+		return (void __user *)-1L;
+
+	switch (insn->addr_bytes) {
+	case 4:
+		return get_addr_ref_32(insn, regs);
+	case 8:
+		return get_addr_ref_64(insn, regs);
+	default:
+		return (void __user *)-1L;
+	}
+}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v11 04/12] x86/insn-eval: Handle 32-bit address encodings in virtual-8086 mode
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
                   ` (2 preceding siblings ...)
  2017-11-06  2:27 ` [PATCH v11 03/12] x86/insn-eval: Add wrapper function for 32 and 64-bit addresses Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08 10:59   ` [tip:x86/asm] " tip-bot for Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 05/12] x86/insn-eval: Add support to resolve 16-bit address encodings Ricardo Neri
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Adam Buchbinder, Colin Ian King, Lorenzo Stoakes, Qiaowei Ren,
	Arnaldo Carvalho de Melo, Adrian Hunter, Kees Cook,
	Thomas Garnier, Dmitry Vyukov

It is possible to utilize 32-bit address encodings in virtual-8086 mode via
an address override instruction prefix. However, the range of the
effective address is still limited to [0x-0xffff]. In such a case, return
error.

Also, linear addresses in virtual-8086 mode are limited to 20 bits. Enforce
such limit by truncating the most significant bytes of the computed linear
address.

Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Colin Ian King <colin.king@canonical.com>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: x86@kernel.org
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 arch/x86/lib/insn-eval.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index 1ac3973..ef102db 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -1042,12 +1042,23 @@ static void __user *get_addr_ref_32(struct insn *insn, struct pt_regs *regs)
 		goto out;
 
 	/*
+	 * Even though 32-bit address encodings are allowed in virtual-8086
+	 * mode, the address range is still limited to [0x-0xffff].
+	 */
+	if (v8086_mode(regs) && (eff_addr & ~0xffff))
+		goto out;
+
+	/*
 	 * Data type long could be 64 bits in size. Ensure that our 32-bit
 	 * effective address is not sign-extended when computing the linear
 	 * address.
 	 */
 	linear_addr = (unsigned long)(eff_addr & 0xffffffff) + seg_base;
 
+	/* Limit linear address to 20 bits */
+	if (v8086_mode(regs))
+		linear_addr &= 0xfffff;
+
 out:
 	return (void __user *)linear_addr;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v11 05/12] x86/insn-eval: Add support to resolve 16-bit address encodings
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
                   ` (3 preceding siblings ...)
  2017-11-06  2:27 ` [PATCH v11 04/12] x86/insn-eval: Handle 32-bit address encodings in virtual-8086 mode Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08 10:59   ` [tip:x86/asm] " tip-bot for Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 06/12] x86/cpufeature: Add User-Mode Instruction Prevention definitions Ricardo Neri
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Adam Buchbinder, Colin Ian King, Lorenzo Stoakes, Qiaowei Ren,
	Arnaldo Carvalho de Melo, Adrian Hunter, Kees Cook,
	Thomas Garnier, Dmitry Vyukov

Tasks running in virtual-8086 mode, in protected mode with code segment
descriptors that specify 16-bit default address sizes via the D bit, or via
an address override prefix will use 16-bit addressing form encodings as
described in the Intel 64 and IA-32 Architecture Software Developer's
Manual Volume 2A Section 2.1.5, Table 2-1.

16-bit addressing encodings differ in several ways from the 32-bit/64-bit
addressing form encodings: ModRM.rm points to different registers and, in
some cases, effective addresses are indicated by the addition of the value
of two registers. Also, there is no support for SIB bytes. Thus, a
separate function is needed to parse this form of addressing.

Three functions are introduced. get_reg_offset_16() obtains the
offset from the base of pt_regs of the registers indicated by the ModRM
byte of the address encoding. get_eff_addr_modrm_16() computes the
effective address from the value of the register operands.
get_addr_ref_16() computes the linear address using the obtained effective
address and the base address of the segment.

Segment limits are enforced when running in protected mode.

Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Colin Ian King <colin.king@canonical.com>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: x86@kernel.org
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 arch/x86/lib/insn-eval.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 212 insertions(+), 1 deletion(-)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index ef102db..35625d2 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -481,6 +481,80 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
 }
 
 /**
+ * get_reg_offset_16() - Obtain offset of register indicated by instruction
+ * @insn:	Instruction containing ModRM byte
+ * @regs:	Register values as seen when entering kernel mode
+ * @offs1:	Offset of the first operand register
+ * @offs2:	Offset of the second opeand register, if applicable
+ *
+ * Obtain the offset, in pt_regs, of the registers indicated by the ModRM byte
+ * in @insn. This function is to be used with 16-bit address encodings. The
+ * @offs1 and @offs2 will be written with the offset of the two registers
+ * indicated by the instruction. In cases where any of the registers is not
+ * referenced by the instruction, the value will be set to -EDOM.
+ *
+ * Returns:
+ *
+ * 0 on success, -EINVAL on error.
+ */
+static int get_reg_offset_16(struct insn *insn, struct pt_regs *regs,
+			     int *offs1, int *offs2)
+{
+	/*
+	 * 16-bit addressing can use one or two registers. Specifics of
+	 * encodings are given in Table 2-1. "16-Bit Addressing Forms with the
+	 * ModR/M Byte" of the Intel Software Development Manual.
+	 */
+	static const int regoff1[] = {
+		offsetof(struct pt_regs, bx),
+		offsetof(struct pt_regs, bx),
+		offsetof(struct pt_regs, bp),
+		offsetof(struct pt_regs, bp),
+		offsetof(struct pt_regs, si),
+		offsetof(struct pt_regs, di),
+		offsetof(struct pt_regs, bp),
+		offsetof(struct pt_regs, bx),
+	};
+
+	static const int regoff2[] = {
+		offsetof(struct pt_regs, si),
+		offsetof(struct pt_regs, di),
+		offsetof(struct pt_regs, si),
+		offsetof(struct pt_regs, di),
+		-EDOM,
+		-EDOM,
+		-EDOM,
+		-EDOM,
+	};
+
+	if (!offs1 || !offs2)
+		return -EINVAL;
+
+	/* Operand is a register, use the generic function. */
+	if (X86_MODRM_MOD(insn->modrm.value) == 3) {
+		*offs1 = insn_get_modrm_rm_off(insn, regs);
+		*offs2 = -EDOM;
+		return 0;
+	}
+
+	*offs1 = regoff1[X86_MODRM_RM(insn->modrm.value)];
+	*offs2 = regoff2[X86_MODRM_RM(insn->modrm.value)];
+
+	/*
+	 * If ModRM.mod is 0 and ModRM.rm is 110b, then we use displacement-
+	 * only addressing. This means that no registers are involved in
+	 * computing the effective address. Thus, ensure that the first
+	 * register offset is invalild. The second register offset is already
+	 * invalid under the aforementioned conditions.
+	 */
+	if ((X86_MODRM_MOD(insn->modrm.value) == 0) &&
+	    (X86_MODRM_RM(insn->modrm.value) == 6))
+		*offs1 = -EDOM;
+
+	return 0;
+}
+
+/**
  * get_desc() - Obtain pointer to a segment descriptor
  * @sel:	Segment selector
  *
@@ -815,7 +889,9 @@ static int get_eff_addr_reg(struct insn *insn, struct pt_regs *regs,
 		return -EINVAL;
 
 	/* Ignore bytes that are outside the address size. */
-	if (insn->addr_bytes == 4)
+	if (insn->addr_bytes == 2)
+		*eff_addr = regs_get_register(regs, *regoff) & 0xffff;
+	else if (insn->addr_bytes == 4)
 		*eff_addr = regs_get_register(regs, *regoff) & 0xffffffff;
 	else /* 64-bit address */
 		*eff_addr = regs_get_register(regs, *regoff);
@@ -891,6 +967,74 @@ static int get_eff_addr_modrm(struct insn *insn, struct pt_regs *regs,
 }
 
 /**
+ * get_eff_addr_modrm_16() - Obtain referenced effective address via ModRM
+ * @insn:	Instruction. Must be valid.
+ * @regs:	Register values as seen when entering kernel mode
+ * @regoff:	Obtained operand offset, in pt_regs, associated with segment
+ * @eff_addr:	Obtained effective address
+ *
+ * Obtain the 16-bit effective address referenced by the ModRM byte of @insn.
+ * After identifying the registers involved in the register-indirect memory
+ * reference, its value is obtained from the operands in @regs. The computed
+ * address is stored @eff_addr. Also, the register operand that indicates
+ * the associated segment is stored in @regoff, this parameter can later be used
+ * to determine such segment.
+ *
+ * Returns:
+ *
+ * 0 on success. @eff_addr will have the referenced effective address. @regoff
+ * will have a register, as an offset from the base of pt_regs, that can be used
+ * to resolve the associated segment.
+ *
+ * -EINVAL on error.
+ */
+static int get_eff_addr_modrm_16(struct insn *insn, struct pt_regs *regs,
+				 int *regoff, short *eff_addr)
+{
+	int addr_offset1, addr_offset2, ret;
+	short addr1 = 0, addr2 = 0, displacement;
+
+	if (insn->addr_bytes != 2)
+		return -EINVAL;
+
+	insn_get_modrm(insn);
+
+	if (!insn->modrm.nbytes)
+		return -EINVAL;
+
+	if (X86_MODRM_MOD(insn->modrm.value) > 2)
+		return -EINVAL;
+
+	ret = get_reg_offset_16(insn, regs, &addr_offset1, &addr_offset2);
+	if (ret < 0)
+		return -EINVAL;
+
+	/*
+	 * Don't fail on invalid offset values. They might be invalid because
+	 * they cannot be used for this particular value of ModRM. Instead, use
+	 * them in the computation only if they contain a valid value.
+	 */
+	if (addr_offset1 != -EDOM)
+		addr1 = regs_get_register(regs, addr_offset1) & 0xffff;
+
+	if (addr_offset2 != -EDOM)
+		addr2 = regs_get_register(regs, addr_offset2) & 0xffff;
+
+	displacement = insn->displacement.value & 0xffff;
+	*eff_addr = addr1 + addr2 + displacement;
+
+	/*
+	 * The first operand register could indicate to use of either SS or DS
+	 * registers to obtain the segment selector.  The second operand
+	 * register can only indicate the use of DS. Thus, the first operand
+	 * will be used to obtain the segment selector.
+	 */
+	*regoff = addr_offset1;
+
+	return 0;
+}
+
+/**
  * get_eff_addr_sib() - Obtain referenced effective address via SIB
  * @insn:	Instruction. Must be valid.
  * @regs:	Register values as seen when entering kernel mode
@@ -975,6 +1119,71 @@ static int get_eff_addr_sib(struct insn *insn, struct pt_regs *regs,
 }
 
 /**
+ * get_addr_ref_16() - Obtain the 16-bit address referred by instruction
+ * @insn:	Instruction containing ModRM byte and displacement
+ * @regs:	Register values as seen when entering kernel mode
+ *
+ * This function is to be used with 16-bit address encodings. Obtain the memory
+ * address referred by the instruction's ModRM and displacement bytes. Also, the
+ * segment used as base is determined by either any segment override prefixes in
+ * @insn or the default segment of the registers involved in the address
+ * computation. In protected mode, segment limits are enforced.
+ *
+ * Returns:
+ *
+ * Linear address referenced by the instruction operands on success.
+ *
+ * -1L on error.
+ */
+static void __user *get_addr_ref_16(struct insn *insn, struct pt_regs *regs)
+{
+	unsigned long linear_addr = -1L, seg_base, seg_limit;
+	int ret, regoff;
+	short eff_addr;
+	long tmp;
+
+	insn_get_modrm(insn);
+	insn_get_displacement(insn);
+
+	if (insn->addr_bytes != 2)
+		goto out;
+
+	if (X86_MODRM_MOD(insn->modrm.value) == 3) {
+		ret = get_eff_addr_reg(insn, regs, &regoff, &tmp);
+		if (ret)
+			goto out;
+
+		eff_addr = tmp;
+	} else {
+		ret = get_eff_addr_modrm_16(insn, regs, &regoff, &eff_addr);
+		if (ret)
+			goto out;
+	}
+
+	ret = get_seg_base_limit(insn, regs, regoff, &seg_base, &seg_limit);
+	if (ret)
+		goto out;
+
+	/*
+	 * Before computing the linear address, make sure the effective address
+	 * is within the limits of the segment. In virtual-8086 mode, segment
+	 * limits are not enforced. In such a case, the segment limit is -1L to
+	 * reflect this fact.
+	 */
+	if ((unsigned long)(eff_addr & 0xffff) > seg_limit)
+		goto out;
+
+	linear_addr = (unsigned long)(eff_addr & 0xffff) + seg_base;
+
+	/* Limit linear address to 20 bits */
+	if (v8086_mode(regs))
+		linear_addr &= 0xfffff;
+
+out:
+	return (void __user *)linear_addr;
+}
+
+/**
  * get_addr_ref_32() - Obtain a 32-bit linear address
  * @insn:	Instruction with ModRM, SIB bytes and displacement
  * @regs:	Register values as seen when entering kernel mode
@@ -1143,6 +1352,8 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 		return (void __user *)-1L;
 
 	switch (insn->addr_bytes) {
+	case 2:
+		return get_addr_ref_16(insn, regs);
 	case 4:
 		return get_addr_ref_32(insn, regs);
 	case 8:
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v11 06/12] x86/cpufeature: Add User-Mode Instruction Prevention definitions
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
                   ` (4 preceding siblings ...)
  2017-11-06  2:27 ` [PATCH v11 05/12] x86/insn-eval: Add support to resolve 16-bit address encodings Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08 10:59   ` [tip:x86/asm] " tip-bot for Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 07/12] x86: Add emulation code for UMIP instructions Ricardo Neri
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Fenghua Yu

User-Mode Instruction Prevention is a security feature present in new
Intel processors that, when set, prevents the execution of a subset of
instructions if such instructions are executed in user mode (CPL > 0).
Attempting to execute such instructions causes a general protection
exception.

The subset of instructions comprises:

 * SGDT - Store Global Descriptor Table
 * SIDT - Store Interrupt Descriptor Table
 * SLDT - Store Local Descriptor Table
 * SMSW - Store Machine Status Word
 * STR  - Store Task Register

This feature is also added to the list of disabled-features to allow
a cleaner handling of build-time configuration.

Cc: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: x86@kernel.org
Reviewed-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 arch/x86/include/asm/cpufeatures.h          | 1 +
 arch/x86/include/asm/disabled-features.h    | 8 +++++++-
 arch/x86/include/uapi/asm/processor-flags.h | 2 ++
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index cdf5be8..c0b0e9e 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -296,6 +296,7 @@
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ECX), word 16 */
 #define X86_FEATURE_AVX512VBMI		(16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
+#define X86_FEATURE_UMIP		(16*32+ 2) /* User Mode Instruction Protection */
 #define X86_FEATURE_PKU			(16*32+ 3) /* Protection Keys for Userspace */
 #define X86_FEATURE_OSPKE		(16*32+ 4) /* OS Protection Keys Enable */
 #define X86_FEATURE_AVX512_VBMI2	(16*32+ 6) /* Additional AVX512 Vector Bit Manipulation Instructions */
diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
index c10c912..14d6d50 100644
--- a/arch/x86/include/asm/disabled-features.h
+++ b/arch/x86/include/asm/disabled-features.h
@@ -16,6 +16,12 @@
 # define DISABLE_MPX	(1<<(X86_FEATURE_MPX & 31))
 #endif
 
+#ifdef CONFIG_X86_INTEL_UMIP
+# define DISABLE_UMIP	0
+#else
+# define DISABLE_UMIP	(1<<(X86_FEATURE_UMIP & 31))
+#endif
+
 #ifdef CONFIG_X86_64
 # define DISABLE_VME		(1<<(X86_FEATURE_VME & 31))
 # define DISABLE_K6_MTRR	(1<<(X86_FEATURE_K6_MTRR & 31))
@@ -63,7 +69,7 @@
 #define DISABLED_MASK13	0
 #define DISABLED_MASK14	0
 #define DISABLED_MASK15	0
-#define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57)
+#define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57|DISABLE_UMIP)
 #define DISABLED_MASK17	0
 #define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
 
diff --git a/arch/x86/include/uapi/asm/processor-flags.h b/arch/x86/include/uapi/asm/processor-flags.h
index 53b4ca5..7e1e730 100644
--- a/arch/x86/include/uapi/asm/processor-flags.h
+++ b/arch/x86/include/uapi/asm/processor-flags.h
@@ -105,6 +105,8 @@
 #define X86_CR4_OSFXSR		_BITUL(X86_CR4_OSFXSR_BIT)
 #define X86_CR4_OSXMMEXCPT_BIT	10 /* enable unmasked SSE exceptions */
 #define X86_CR4_OSXMMEXCPT	_BITUL(X86_CR4_OSXMMEXCPT_BIT)
+#define X86_CR4_UMIP_BIT	11 /* enable UMIP support */
+#define X86_CR4_UMIP		_BITUL(X86_CR4_UMIP_BIT)
 #define X86_CR4_LA57_BIT	12 /* enable 5-level page tables */
 #define X86_CR4_LA57		_BITUL(X86_CR4_LA57_BIT)
 #define X86_CR4_VMXE_BIT	13 /* enable VMX virtualization */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v11 07/12] x86: Add emulation code for UMIP instructions
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
                   ` (5 preceding siblings ...)
  2017-11-06  2:27 ` [PATCH v11 06/12] x86/cpufeature: Add User-Mode Instruction Prevention definitions Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08 11:00   ` [tip:x86/asm] x86/umip: " tip-bot for Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 08/12] x86/umip: Force a page fault when unable to copy emulated result to user Ricardo Neri
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Fenghua Yu

The feature User-Mode Instruction Prevention present in recent Intel
processor prevents a group of instructions (sgdt, sidt, sldt, smsw, and
str) from being executed with CPL > 0. Otherwise, a general protection
fault is issued.

Rather than relaying to the user space the general protection fault caused
by the UMIP-protected instructions (in the form of a SIGSEGV signal), it
can be trapped and the instruction emulated to provide a dummy result.
This allows to both conserve the current kernel behavior and not reveal the
system resources that UMIP intends to protect (i.e., the locations of the
global descriptor and interrupt descriptor tables, the segment selectors of
the local descriptor table, the value of the task state register and the
contents of the CR0 register).

This emulation is needed because certain applications (e.g., WineHQ and
DOSEMU2) rely on this subset of instructions to function. Given that sldt
and str are not commonly used in programs that run on WineHQ or DOSEMU2,
they are not emulated. Also, emulation is provided only for 32-bit
processes; 64-bit processes that attempt to use the instructions that UMIP
protects will receive the SIGSEGV signal issued as a consequence of the
general protection fault.

The instructions protected by UMIP can be split in two groups. Those which
return a kernel memory address (sgdt and sidt) and those which return a
value (smsw, sldt and str; the last two not emulated).

For the instructions that return a kernel memory address, applications such
as WineHQ rely on the result being located in the kernel memory space, not
the actual location of the table. The result is emulated as a hard-coded
value that lies close to the top of the kernel memory. The limit for the
GDT and the IDT are set to zero.

The instruction smsw is emulated to return the value that the register CR0
has at boot time as set in the head_32.

Care is taken to appropriately emulate the results when segmentation is
used. That is, rather than relying on USER_DS and USER_CS, the function
insn_get_addr_ref() inspects the segment descriptor pointed by the
registers in pt_regs. This ensures that we correctly obtain the segment
base address and the address and operand sizes even if the user space
application uses a local descriptor table.

Cc: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: x86@kernel.org
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 arch/x86/include/asm/umip.h |  12 ++
 arch/x86/kernel/Makefile    |   1 +
 arch/x86/kernel/umip.c      | 321 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 334 insertions(+)
 create mode 100644 arch/x86/include/asm/umip.h
 create mode 100644 arch/x86/kernel/umip.c

diff --git a/arch/x86/include/asm/umip.h b/arch/x86/include/asm/umip.h
new file mode 100644
index 0000000..db43f2a
--- /dev/null
+++ b/arch/x86/include/asm/umip.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_X86_UMIP_H
+#define _ASM_X86_UMIP_H
+
+#include <linux/types.h>
+#include <asm/ptrace.h>
+
+#ifdef CONFIG_X86_INTEL_UMIP
+bool fixup_umip_exception(struct pt_regs *regs);
+#else
+static inline bool fixup_umip_exception(struct pt_regs *regs) { return false; }
+#endif  /* CONFIG_X86_INTEL_UMIP */
+#endif  /* _ASM_X86_UMIP_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 295abaa..81bb565 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -127,6 +127,7 @@ obj-$(CONFIG_EFI)			+= sysfb_efi.o
 obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 obj-$(CONFIG_TRACING)			+= tracepoint.o
 obj-$(CONFIG_SCHED_MC_PRIO)		+= itmt.o
+obj-$(CONFIG_X86_INTEL_UMIP)		+= umip.o
 
 obj-$(CONFIG_UNWINDER_ORC)		+= unwind_orc.o
 obj-$(CONFIG_UNWINDER_FRAME_POINTER)	+= unwind_frame.o
diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
new file mode 100644
index 0000000..d80b816
--- /dev/null
+++ b/arch/x86/kernel/umip.c
@@ -0,0 +1,321 @@
+/*
+ * umip.c Emulation for instruction protected by the Intel User-Mode
+ * Instruction Prevention feature
+ *
+ * Copyright (c) 2017, Intel Corporation.
+ * Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
+ */
+
+#include <linux/uaccess.h>
+#include <asm/umip.h>
+#include <asm/traps.h>
+#include <asm/insn.h>
+#include <asm/insn-eval.h>
+
+/** DOC: Emulation for User-Mode Instruction Prevention (UMIP)
+ *
+ * The feature User-Mode Instruction Prevention present in recent Intel
+ * processor prevents a group of instructions (sgdt, sidt, sldt, smsw, and str)
+ * from being executed with CPL > 0. Otherwise, a general protection fault is
+ * issued.
+ *
+ * Rather than relaying to the user space the general protection fault caused by
+ * the UMIP-protected instructions (in the form of a SIGSEGV signal), it can be
+ * trapped and emulate the result of such instructions to provide dummy values.
+ * This allows to both conserve the current kernel behavior and not reveal the
+ * system resources that UMIP intends to protect (i.e., the locations of the
+ * global descriptor and interrupt descriptor tables, the segment selectors of
+ * the local descriptor table, the value of the task state register and the
+ * contents of the CR0 register).
+ *
+ * This emulation is needed because certain applications (e.g., WineHQ and
+ * DOSEMU2) rely on this subset of instructions to function.
+ *
+ * The instructions protected by UMIP can be split in two groups. Those which
+ * return a kernel memory address (sgdt and sidt) and those which return a
+ * value (sldt, str and smsw).
+ *
+ * For the instructions that return a kernel memory address, applications
+ * such as WineHQ rely on the result being located in the kernel memory space,
+ * not the actual location of the table. The result is emulated as a hard-coded
+ * value that, lies close to the top of the kernel memory. The limit for the GDT
+ * and the IDT are set to zero.
+ *
+ * Given that sldt and str are not commonly used in programs that run on WineHQ
+ * or DOSEMU2, they are not emulated.
+ *
+ * The instruction smsw is emulated to return the value that the register CR0
+ * has at boot time as set in the head_32.
+ *
+ * Also, emulation is provided only for 32-bit processes; 64-bit processes
+ * that attempt to use the instructions that UMIP protects will receive the
+ * SIGSEGV signal issued as a consequence of the general protection fault.
+ *
+ * Care is taken to appropriately emulate the results when segmentation is
+ * used. That is, rather than relying on USER_DS and USER_CS, the function
+ * insn_get_addr_ref() inspects the segment descriptor pointed by the
+ * registers in pt_regs. This ensures that we correctly obtain the segment
+ * base address and the address and operand sizes even if the user space
+ * application uses a local descriptor table.
+ */
+
+#define UMIP_DUMMY_GDT_BASE 0xfffe0000
+#define UMIP_DUMMY_IDT_BASE 0xffff0000
+
+/*
+ * The SGDT and SIDT instructions store the contents of the global descriptor
+ * table and interrupt table registers, respectively. The destination is a
+ * memory operand of X+2 bytes. X bytes are used to store the base address of
+ * the table and 2 bytes are used to store the limit. In 32-bit processes, the
+ * only processes for which emulation is provided, X has a value of 4.
+ */
+#define UMIP_GDT_IDT_BASE_SIZE 4
+#define UMIP_GDT_IDT_LIMIT_SIZE 2
+
+#define	UMIP_INST_SGDT	0	/* 0F 01 /0 */
+#define	UMIP_INST_SIDT	1	/* 0F 01 /1 */
+#define	UMIP_INST_SMSW	3	/* 0F 01 /4 */
+
+/**
+ * identify_insn() - Identify a UMIP-protected instruction
+ * @insn:	Instruction structure with opcode and ModRM byte.
+ *
+ * From the opcode and ModRM.reg in @insn identify, if any, a UMIP-protected
+ * instruction that can be emulated.
+ *
+ * Returns:
+ *
+ * On success, a constant identifying a specific UMIP-protected instruction that
+ * can be emulated.
+ *
+ * -EINVAL on error or when not an UMIP-protected instruction that can be
+ * emulated.
+ */
+static int identify_insn(struct insn *insn)
+{
+	/* By getting modrm we also get the opcode. */
+	insn_get_modrm(insn);
+
+	if (!insn->modrm.nbytes)
+		return -EINVAL;
+
+	/* All the instructions of interest start with 0x0f. */
+	if (insn->opcode.bytes[0] != 0xf)
+		return -EINVAL;
+
+	if (insn->opcode.bytes[1] == 0x1) {
+		switch (X86_MODRM_REG(insn->modrm.value)) {
+		case 0:
+			return UMIP_INST_SGDT;
+		case 1:
+			return UMIP_INST_SIDT;
+		case 4:
+			return UMIP_INST_SMSW;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	/* SLDT AND STR are not emulated */
+	return -EINVAL;
+}
+
+/**
+ * emulate_umip_insn() - Emulate UMIP instructions and return dummy values
+ * @insn:	Instruction structure with operands
+ * @umip_inst:	A constant indicating the instruction to emulate
+ * @data:	Buffer into which the dummy result is stored
+ * @data_size:	Size of the emulated result
+ *
+ * Emulate an instruction protected by UMIP and provide a dummy result. The
+ * result of the emulation is saved in @data. The size of the results depends
+ * on both the instruction and type of operand (register vs memory address).
+ * The size of the result is updated in @data_size. Caller is responsible
+ * of providing a @data buffer of at least UMIP_GDT_IDT_BASE_SIZE +
+ * UMIP_GDT_IDT_LIMIT_SIZE bytes.
+ *
+ * Returns:
+ *
+ * 0 on success, -EINVAL on error while emulating.
+ */
+static int emulate_umip_insn(struct insn *insn, int umip_inst,
+			     unsigned char *data, int *data_size)
+{
+	unsigned long dummy_base_addr, dummy_value;
+	unsigned short dummy_limit = 0;
+
+	if (!data || !data_size || !insn)
+		return -EINVAL;
+	/*
+	 * These two instructions return the base address and limit of the
+	 * global and interrupt descriptor table, respectively. According to the
+	 * Intel Software Development manual, the base address can be 24-bit,
+	 * 32-bit or 64-bit. Limit is always 16-bit. If the operand size is
+	 * 16-bit, the returned value of the base address is supposed to be a
+	 * zero-extended 24-byte number. However, it seems that a 32-byte number
+	 * is always returned irrespective of the operand size.
+	 */
+	if (umip_inst == UMIP_INST_SGDT || umip_inst == UMIP_INST_SIDT) {
+		/* SGDT and SIDT do not use registers operands. */
+		if (X86_MODRM_MOD(insn->modrm.value) == 3)
+			return -EINVAL;
+
+		if (umip_inst == UMIP_INST_SGDT)
+			dummy_base_addr = UMIP_DUMMY_GDT_BASE;
+		else
+			dummy_base_addr = UMIP_DUMMY_IDT_BASE;
+
+		*data_size = UMIP_GDT_IDT_LIMIT_SIZE + UMIP_GDT_IDT_BASE_SIZE;
+
+		memcpy(data + 2, &dummy_base_addr, UMIP_GDT_IDT_BASE_SIZE);
+		memcpy(data, &dummy_limit, UMIP_GDT_IDT_LIMIT_SIZE);
+
+	} else if (umip_inst == UMIP_INST_SMSW) {
+		dummy_value = CR0_STATE;
+
+		/*
+		 * Even though the CR0 register has 4 bytes, the number
+		 * of bytes to be copied in the result buffer is determined
+		 * by whether the operand is a register or a memory location.
+		 * If operand is a register, return as many bytes as the operand
+		 * size. If operand is memory, return only the two least
+		 * siginificant bytes of CR0.
+		 */
+		if (X86_MODRM_MOD(insn->modrm.value) == 3)
+			*data_size = insn->opnd_bytes;
+		else
+			*data_size = 2;
+
+		memcpy(data, &dummy_value, *data_size);
+	/* STR and SLDT  are not emulated */
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * fixup_umip_exception() - Fixup a general protection fault caused by UMIP
+ * @regs:	Registers as saved when entering the #GP handler
+ *
+ * The instructions sgdt, sidt, str, smsw, sldt cause a general protection
+ * fault if executed with CPL > 0 (i.e., from user space). If the offending
+ * user-space process is not in long mode, this function fixes the exception
+ * up and provides dummy results for sgdt, sidt and smsw; str and sldt are not
+ * fixed up. Also long mode user-space processes are not fixed up.
+ *
+ * If operands are memory addresses, results are copied to user-space memory as
+ * indicated by the instruction pointed by eIP using the registers indicated in
+ * the instruction operands. If operands are registers, results are copied into
+ * the context that was saved when entering kernel mode.
+ *
+ * Returns:
+ *
+ * True if emulation was successful; false if not.
+ */
+bool fixup_umip_exception(struct pt_regs *regs)
+{
+	int not_copied, nr_copied, reg_offset, dummy_data_size, umip_inst;
+	unsigned long seg_base = 0, *reg_addr;
+	/* 10 bytes is the maximum size of the result of UMIP instructions */
+	unsigned char dummy_data[10] = { 0 };
+	unsigned char buf[MAX_INSN_SIZE];
+	void __user *uaddr;
+	struct insn insn;
+	char seg_defs;
+
+	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
+	 * descriptor table), or virtual-8086 mode. In most of the cases
+	 * seg_base will be zero as in USER_CS.
+	 */
+	if (!user_64bit_mode(regs))
+		seg_base = insn_get_seg_base(regs, INAT_SEG_REG_CS);
+
+	if (seg_base == -1L)
+		return false;
+
+	not_copied = copy_from_user(buf, (void __user *)(seg_base + regs->ip),
+				    sizeof(buf));
+	nr_copied = sizeof(buf) - not_copied;
+
+	/*
+	 * The copy_from_user above could have failed if user code is protected
+	 * by a memory protection key. Give up on emulation in such a case.
+	 * Should we issue a page fault?
+	 */
+	if (!nr_copied)
+		return false;
+
+	insn_init(&insn, buf, nr_copied, user_64bit_mode(regs));
+
+	/*
+	 * Override the default operand and address sizes with what is specified
+	 * in the code segment descriptor. The instruction decoder only sets
+	 * the address size it to either 4 or 8 address bytes and does nothing
+	 * for the operand bytes. This OK for most of the cases, but we could
+	 * have special cases where, for instance, a 16-bit code segment
+	 * descriptor is used.
+	 * If there is an address override prefix, the instruction decoder
+	 * correctly updates these values, even for 16-bit defaults.
+	 */
+	seg_defs = insn_get_code_seg_params(regs);
+	if (seg_defs == -EINVAL)
+		return false;
+
+	insn.addr_bytes = INSN_CODE_SEG_ADDR_SZ(seg_defs);
+	insn.opnd_bytes = INSN_CODE_SEG_OPND_SZ(seg_defs);
+
+	insn_get_length(&insn);
+	if (nr_copied < insn.length)
+		return false;
+
+	umip_inst = identify_insn(&insn);
+	if (umip_inst < 0)
+		return false;
+
+	if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size))
+		return false;
+
+	/*
+	 * If operand is a register, write result to the copy of the register
+	 * value that was pushed to the stack when entering into kernel mode.
+	 * Upon exit, the value we write will be restored to the actual hardware
+	 * register.
+	 */
+	if (X86_MODRM_MOD(insn.modrm.value) == 3) {
+		reg_offset = insn_get_modrm_rm_off(&insn, regs);
+
+		/*
+		 * Negative values are usually errors. In memory addressing,
+		 * the exception is -EDOM. Since we expect a register operand,
+		 * all negative values are errors.
+		 */
+		if (reg_offset < 0)
+			return false;
+
+		reg_addr = (unsigned long *)((unsigned long)regs + reg_offset);
+		memcpy(reg_addr, dummy_data, dummy_data_size);
+	} else {
+		uaddr = insn_get_addr_ref(&insn, regs);
+		if ((unsigned long)uaddr == -1L)
+			return false;
+
+		nr_copied = copy_to_user(uaddr, dummy_data, dummy_data_size);
+		if (nr_copied  > 0)
+			return false;
+	}
+
+	/* increase IP to let the program keep going */
+	regs->ip += insn.length;
+	return true;
+}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v11 08/12] x86/umip: Force a page fault when unable to copy emulated result to user
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
                   ` (6 preceding siblings ...)
  2017-11-06  2:27 ` [PATCH v11 07/12] x86: Add emulation code for UMIP instructions Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08 11:00   ` [tip:x86/asm] " tip-bot for Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 09/12] x86: Enable User-Mode Instruction Prevention at runtime Ricardo Neri
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Fenghua Yu

fixup_umip_exception() will be called from do_general_protection(). If the
former returns false, the latter will issue a SIGSEGV with SEND_SIG_PRIV.
However, when emulation is successful but the emulated result cannot be
copied to user space memory, it is more accurate to issue a SIGSEGV with
SEGV_MAPERR with the offending address. A new function, inspired in
force_sig_info_fault(), is introduced to model the page fault.

Cc: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: x86@kernel.org
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 arch/x86/kernel/umip.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index d80b816..6ba82be 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -11,6 +11,10 @@
 #include <asm/traps.h>
 #include <asm/insn.h>
 #include <asm/insn-eval.h>
+#include <linux/ratelimit.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "umip: " fmt
 
 /** DOC: Emulation for User-Mode Instruction Prevention (UMIP)
  *
@@ -196,6 +200,41 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
 }
 
 /**
+ * force_sig_info_umip_fault() - Force a SIGSEGV with SEGV_MAPERR
+ * @addr:	Address that caused the signal
+ * @regs:	Register set containing the instruction pointer
+ *
+ * Force a SIGSEGV signal with SEGV_MAPERR as the error code. This function is
+ * intended to be used to provide a segmentation fault when the result of the
+ * UMIP emulation could not be copied to the user space memory.
+ *
+ * Returns: none
+ */
+static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs)
+{
+	siginfo_t info;
+	struct task_struct *tsk = current;
+
+	tsk->thread.cr2		= (unsigned long)addr;
+	tsk->thread.error_code	= X86_PF_USER | X86_PF_WRITE;
+	tsk->thread.trap_nr	= X86_TRAP_PF;
+
+	info.si_signo	= SIGSEGV;
+	info.si_errno	= 0;
+	info.si_code	= SEGV_MAPERR;
+	info.si_addr	= addr;
+	force_sig_info(SIGSEGV, &info, tsk);
+
+	if (!(show_unhandled_signals && unhandled_signal(tsk, SIGSEGV)))
+		return;
+
+	pr_err_ratelimited("%s[%d] umip emulation segfault ip:%lx sp:%lx error:%x in %lx\n",
+			   tsk->comm, task_pid_nr(tsk), regs->ip,
+			   regs->sp, X86_PF_USER | X86_PF_WRITE,
+			   regs->ip);
+}
+
+/**
  * fixup_umip_exception() - Fixup a general protection fault caused by UMIP
  * @regs:	Registers as saved when entering the #GP handler
  *
@@ -311,8 +350,14 @@ bool fixup_umip_exception(struct pt_regs *regs)
 			return false;
 
 		nr_copied = copy_to_user(uaddr, dummy_data, dummy_data_size);
-		if (nr_copied  > 0)
-			return false;
+		if (nr_copied  > 0) {
+			/*
+			 * If copy fails, send a signal and tell caller that
+			 * fault was fixed up.
+			 */
+			force_sig_info_umip_fault(uaddr, regs);
+			return true;
+		}
 	}
 
 	/* increase IP to let the program keep going */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v11 09/12] x86: Enable User-Mode Instruction Prevention at runtime
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
                   ` (7 preceding siblings ...)
  2017-11-06  2:27 ` [PATCH v11 08/12] x86/umip: Force a page fault when unable to copy emulated result to user Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08  9:52   ` Ingo Molnar
  2017-11-08 11:01   ` [tip:x86/asm] x86/umip: " tip-bot for Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 10/12] x86/traps: Fixup general protection faults caused by UMIP Ricardo Neri
                   ` (3 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Fenghua Yu

User-Mode Instruction Prevention (UMIP) is enabled by setting/clearing a
bit in %cr4.

It makes 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 user space to be protected from. Given these similarities, UMIP can be
enabled along with SMAP and SMEP.

At the moment, UMIP is disabled by default at build time. It can be enabled
at build time by selecting CONFIG_X86_INTEL_UMIP. If enabled at build time,
it can be disabled at run time by adding clearcpuid=514 to the kernel
parameters.

Cc: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: x86@kernel.org
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 arch/x86/Kconfig             | 10 ++++++++++
 arch/x86/kernel/cpu/common.c | 25 ++++++++++++++++++++++++-
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 38da9bb..f08977d 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1804,6 +1804,16 @@ config X86_SMAP
 
 	  If unsure, say Y.
 
+config X86_INTEL_UMIP
+	def_bool n
+	depends on CPU_SUP_INTEL
+	prompt "Intel 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 f8bea7f..13ae9e5 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -329,6 +329,28 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c)
 	}
 }
 
+static __always_inline void setup_umip(struct cpuinfo_x86 *c)
+{
+	/* Check the boot processor, plus build option for UMIP. */
+	if (!cpu_feature_enabled(X86_FEATURE_UMIP))
+		goto out;
+
+	/* Check the current processor's cpuid bits. */
+	if (!cpu_has(c, X86_FEATURE_UMIP))
+		goto out;
+
+	cr4_set_bits(X86_CR4_UMIP);
+
+	return;
+
+out:
+	/*
+	 * 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.
  */
@@ -1147,9 +1169,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

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v11 10/12] x86/traps: Fixup general protection faults caused by UMIP
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
                   ` (8 preceding siblings ...)
  2017-11-06  2:27 ` [PATCH v11 09/12] x86: Enable User-Mode Instruction Prevention at runtime Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08 11:01   ` [tip:x86/asm] x86/traps: Fix up " tip-bot for Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 11/12] selftests/x86: Add tests for User-Mode Instruction Prevention Ricardo Neri
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Fenghua Yu

If the User-Mode Instruction Prevention CPU feature is available and
enabled, a general protection fault will be issued if the instructions
sgdt, sldt, sidt, str or smsw are executed from user-mode context
(CPL > 0). If the fault was caused by any of the instructions protected
by UMIP, fixup_umip_exception() will emulate dummy results for these
instructions as follows: in virtual-8086 and protected modes, sgdt, sidt
and smsw are emulated; str and sldt are not emulated. No emulation is done
for user-space long mode processes.

If emulation is successful, the emulated result is passed to the user space
program and no SIGSEGV signal is emitted.

Cc: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: x86@kernel.org
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 arch/x86/kernel/traps.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 9aab8b8..abf4f28 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -60,6 +60,7 @@
 #include <asm/trace/mpx.h>
 #include <asm/mpx.h>
 #include <asm/vm86.h>
+#include <asm/umip.h>
 
 #ifdef CONFIG_X86_64
 #include <asm/x86_init.h>
@@ -513,6 +514,10 @@ do_general_protection(struct pt_regs *regs, long error_code)
 	RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
 	cond_local_irq_enable(regs);
 
+	if (static_cpu_has(X86_FEATURE_UMIP))
+		if (user_mode(regs) && fixup_umip_exception(regs))
+			return;
+
 	if (v8086_mode(regs)) {
 		local_irq_enable();
 		handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v11 11/12] selftests/x86: Add tests for User-Mode Instruction Prevention
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
                   ` (9 preceding siblings ...)
  2017-11-06  2:27 ` [PATCH v11 10/12] x86/traps: Fixup general protection faults caused by UMIP Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08 11:02   ` [tip:x86/asm] " tip-bot for Ricardo Neri
  2017-11-06  2:27 ` [PATCH v11 12/12] selftests/x86: Add tests for instruction str and sldt Ricardo Neri
  2017-11-08 10:00 ` [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Thomas Gleixner
  12 siblings, 1 reply; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Fenghua Yu

Certain user space programs that run on virtual-8086 mode may utilize
instructions protected by the User-Mode Instruction Prevention (UMIP)
security feature present in new Intel processors: SGDT, SIDT and SMSW. In
such a case, a general protection fault is issued if UMIP is enabled. When
such a fault happens, the kernel traps it and emulates the results of
these instructions with dummy values. The purpose of this new
test is to verify whether the impacted instructions can be executed
without causing such #GP. If no #GP exceptions occur, we expect to exit
virtual-8086 mode from INT3.

The instructions protected by UMIP are executed in representative use
cases:
 a) displacement-only memory addressing
 b) register-indirect memory addressing
 c) results stored directly in operands

Unfortunately, it is not possible to check the results against a set of
expected values because no emulation will occur in systems that do not
have the UMIP feature. Instead, results are printed for verification. A
simple verification is done to ensure that results of all tests are
identical.

Cc: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 tools/testing/selftests/x86/entry_from_vm86.c | 73 ++++++++++++++++++++++++++-
 1 file changed, 72 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c
index d075ea0..f7d9cea 100644
--- a/tools/testing/selftests/x86/entry_from_vm86.c
+++ b/tools/testing/selftests/x86/entry_from_vm86.c
@@ -95,6 +95,22 @@ asm (
 	"int3\n\t"
 	"vmcode_int80:\n\t"
 	"int $0x80\n\t"
+	"vmcode_umip:\n\t"
+	/* addressing via displacements */
+	"smsw (2052)\n\t"
+	"sidt (2054)\n\t"
+	"sgdt (2060)\n\t"
+	/* addressing via registers */
+	"mov $2066, %bx\n\t"
+	"smsw (%bx)\n\t"
+	"mov $2068, %bx\n\t"
+	"sidt (%bx)\n\t"
+	"mov $2074, %bx\n\t"
+	"sgdt (%bx)\n\t"
+	/* register operands, only for smsw */
+	"smsw %ax\n\t"
+	"mov %ax, (2080)\n\t"
+	"int3\n\t"
 	".size vmcode, . - vmcode\n\t"
 	"end_vmcode:\n\t"
 	".code32\n\t"
@@ -103,7 +119,7 @@ asm (
 
 extern unsigned char vmcode[], end_vmcode[];
 extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[],
-	vmcode_sti[], vmcode_int3[], vmcode_int80[];
+	vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[];
 
 /* Returns false if the test was skipped. */
 static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
@@ -160,6 +176,58 @@ static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
 	return true;
 }
 
+void do_umip_tests(struct vm86plus_struct *vm86, unsigned char *test_mem)
+{
+	struct table_desc {
+		unsigned short limit;
+		unsigned long base;
+	} __attribute__((packed));
+
+	/* Initialize variables with arbitrary values */
+	struct table_desc gdt1 = { .base = 0x3c3c3c3c, .limit = 0x9999 };
+	struct table_desc gdt2 = { .base = 0x1a1a1a1a, .limit = 0xaeae };
+	struct table_desc idt1 = { .base = 0x7b7b7b7b, .limit = 0xf1f1 };
+	struct table_desc idt2 = { .base = 0x89898989, .limit = 0x1313 };
+	unsigned short msw1 = 0x1414, msw2 = 0x2525, msw3 = 3737;
+
+	/* UMIP -- exit with INT3 unless kernel emulation did not trap #GP */
+	do_test(vm86, vmcode_umip - vmcode, VM86_TRAP, 3, "UMIP tests");
+
+	/* Results from displacement-only addressing */
+	msw1 = *(unsigned short *)(test_mem + 2052);
+	memcpy(&idt1, test_mem + 2054, sizeof(idt1));
+	memcpy(&gdt1, test_mem + 2060, sizeof(gdt1));
+
+	/* Results from register-indirect addressing */
+	msw2 = *(unsigned short *)(test_mem + 2066);
+	memcpy(&idt2, test_mem + 2068, sizeof(idt2));
+	memcpy(&gdt2, test_mem + 2074, sizeof(gdt2));
+
+	/* Results when using register operands */
+	msw3 = *(unsigned short *)(test_mem + 2080);
+
+	printf("[INFO]\tResult from SMSW:[0x%04x]\n", msw1);
+	printf("[INFO]\tResult from SIDT: limit[0x%04x]base[0x%08lx]\n",
+	       idt1.limit, idt1.base);
+	printf("[INFO]\tResult from SGDT: limit[0x%04x]base[0x%08lx]\n",
+	       gdt1.limit, gdt1.base);
+
+	if (msw1 != msw2 || msw1 != msw3)
+		printf("[FAIL]\tAll the results of SMSW should be the same.\n");
+	else
+		printf("[PASS]\tAll the results from SMSW are identical.\n");
+
+	if (memcmp(&gdt1, &gdt2, sizeof(gdt1)))
+		printf("[FAIL]\tAll the results of SGDT should be the same.\n");
+	else
+		printf("[PASS]\tAll the results from SGDT are identical.\n");
+
+	if (memcmp(&idt1, &idt2, sizeof(idt1)))
+		printf("[FAIL]\tAll the results of SIDT should be the same.\n");
+	else
+		printf("[PASS]\tAll the results from SIDT are identical.\n");
+}
+
 int main(void)
 {
 	struct vm86plus_struct v86;
@@ -218,6 +286,9 @@ int main(void)
 	v86.regs.eax = (unsigned int)-1;
 	do_test(&v86, vmcode_int80 - vmcode, VM86_INTx, 0x80, "int80");
 
+	/* UMIP -- should exit with INTx 0x80 unless UMIP was not disabled */
+	do_umip_tests(&v86, addr);
+
 	/* Execute a null pointer */
 	v86.regs.cs = 0;
 	v86.regs.ss = 0;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v11 12/12] selftests/x86: Add tests for instruction str and sldt
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
                   ` (10 preceding siblings ...)
  2017-11-06  2:27 ` [PATCH v11 11/12] selftests/x86: Add tests for User-Mode Instruction Prevention Ricardo Neri
@ 2017-11-06  2:27 ` Ricardo Neri
  2017-11-08 11:02   ` [tip:x86/asm] selftests/x86: Add tests for the STR and SLDT instructions tip-bot for Ricardo Neri
  2017-11-08 10:00 ` [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Thomas Gleixner
  12 siblings, 1 reply; 41+ messages in thread
From: Ricardo Neri @ 2017-11-06  2:27 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov
  Cc: Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck, Ricardo Neri,
	Fenghua Yu

The instructions str and sldt are not valid when running on virtual-8086
mode and generate an invalid operand exception. These two instructions are
protected by the Intel User-Mode Instruction Prevention (UMIP) security
feature. In protected mode, if UMIP is enabled, these instructions generate
a general protection fault if called from CPL > 0. Linux traps the general
protection fault and emulates the instructions sgdt, sidt and smsw; but not
str and sldt.

These tests are added to verify that the emulation code does not emulate
these two instructions but the expected invalid operand exception is
seen.

Tests fallback to exit with int3 in case emulation does happen.

Cc: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 tools/testing/selftests/x86/entry_from_vm86.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c
index f7d9cea..361466a 100644
--- a/tools/testing/selftests/x86/entry_from_vm86.c
+++ b/tools/testing/selftests/x86/entry_from_vm86.c
@@ -111,6 +111,11 @@ asm (
 	"smsw %ax\n\t"
 	"mov %ax, (2080)\n\t"
 	"int3\n\t"
+	"vmcode_umip_str:\n\t"
+	"str %eax\n\t"
+	"vmcode_umip_sldt:\n\t"
+	"sldt %eax\n\t"
+	"int3\n\t"
 	".size vmcode, . - vmcode\n\t"
 	"end_vmcode:\n\t"
 	".code32\n\t"
@@ -119,7 +124,8 @@ asm (
 
 extern unsigned char vmcode[], end_vmcode[];
 extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[],
-	vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[];
+	vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[],
+	vmcode_umip_str[], vmcode_umip_sldt[];
 
 /* Returns false if the test was skipped. */
 static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
@@ -226,6 +232,16 @@ void do_umip_tests(struct vm86plus_struct *vm86, unsigned char *test_mem)
 		printf("[FAIL]\tAll the results of SIDT should be the same.\n");
 	else
 		printf("[PASS]\tAll the results from SIDT are identical.\n");
+
+	sethandler(SIGILL, sighandler, 0);
+	do_test(vm86, vmcode_umip_str - vmcode, VM86_SIGNAL, 0,
+		"STR instruction");
+	clearhandler(SIGILL);
+
+	sethandler(SIGILL, sighandler, 0);
+	do_test(vm86, vmcode_umip_sldt - vmcode, VM86_SIGNAL, 0,
+		"SLDT instruction");
+	clearhandler(SIGILL);
 }
 
 int main(void)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH v11 09/12] x86: Enable User-Mode Instruction Prevention at runtime
  2017-11-06  2:27 ` [PATCH v11 09/12] x86: Enable User-Mode Instruction Prevention at runtime Ricardo Neri
@ 2017-11-08  9:52   ` Ingo Molnar
  2017-11-09  5:51     ` Ricardo Neri
  2017-11-08 11:01   ` [tip:x86/asm] x86/umip: " tip-bot for Ricardo Neri
  1 sibling, 1 reply; 41+ messages in thread
From: Ingo Molnar @ 2017-11-08  9:52 UTC (permalink / raw)
  To: Ricardo Neri
  Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov, Peter Zijlstra, Andrew Morton, Brian Gerst,
	Chris Metcalf, Dave Hansen, Paolo Bonzini, Masami Hiramatsu,
	Huang Rui, Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin,
	Paul Gortmaker, Vlastimil Babka, Chen Yucong, Ravi V. Shankar,
	Shuah Khan, linux-kernel, x86, ricardo.neri, Tony Luck,
	Fenghua Yu


* Ricardo Neri <ricardo.neri-calderon@linux.intel.com> wrote:

> User-Mode Instruction Prevention (UMIP) is enabled by setting/clearing a
> bit in %cr4.
> 
> It makes 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 user space to be protected from. Given these similarities, UMIP can be
> enabled along with SMAP and SMEP.
> 
> At the moment, UMIP is disabled by default at build time. It can be enabled
> at build time by selecting CONFIG_X86_INTEL_UMIP. If enabled at build time,
> it can be disabled at run time by adding clearcpuid=514 to the kernel
> parameters.

> +config X86_INTEL_UMIP
> +	def_bool n
> +	depends on CPU_SUP_INTEL
> +	prompt "Intel 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.

Ok, I really like this latest series.

One small request: could you please make the feature default-y, which is what we 
do for new hardware features that don't have a significant runtime cost. There's 
no ABI breakage expected, right?

Another request: could you please extend the Kconfig description to _explain_ to 
the user why this feature is useful - in a short sentence or so. I.e. point out 
that these instructions expose information about hardware state that is not really 
necessary for the vast majority of applications.

Plus:

> +       cr4_set_bits(X86_CR4_UMIP);

Please also inform admins that it's enabled, via something like:

	pr_info("x86/cpu: Activated the Intel User Mode Instruction Prevention (UMIP) CPU feature\n");

... or so.

Please do these changes in a separate add-on patch #13 on top of this series, as 
I've already started testing these bits.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention
  2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
                   ` (11 preceding siblings ...)
  2017-11-06  2:27 ` [PATCH v11 12/12] selftests/x86: Add tests for instruction str and sldt Ricardo Neri
@ 2017-11-08 10:00 ` Thomas Gleixner
  2017-11-09  5:46   ` Ricardo Neri
  12 siblings, 1 reply; 41+ messages in thread
From: Thomas Gleixner @ 2017-11-08 10:00 UTC (permalink / raw)
  To: Ricardo Neri
  Cc: Ingo Molnar, H. Peter Anvin, Andy Lutomirski, Borislav Petkov,
	Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck

On Sun, 5 Nov 2017, Ricardo Neri wrote:
> Changes since V10:
> *Patch 1 ("x86/insn-eval: Extend get_seg_base_addr() to also obtain segment
>  limit") of v10 has been dropped has it has been merged in the tip tree.
> *Removed unnecessary wrap-around of function calls to enforce the 80
>  chars-per-line rule. In some cases, variables were renamed.
> *Removed unnecessary casts between variables of the same width.
> *Reworked casts between variables of different width in favor of bit
>  masks. Casts were kept for arithmetic operations.
> *Reworded patch descriptions and documentation of several functions to
>  improve clarity.

For the whole series:

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [tip:x86/asm] x86/insn-eval: Compute linear address in several utility functions
  2017-11-06  2:27 ` [PATCH v11 01/12] x86/insn-eval: Compute linear address in several utility functions Ricardo Neri
@ 2017-11-08 10:57   ` tip-bot for Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 10:57 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: vbabka, jpoimboe, tony.luck, mingo, dvyukov, dave.hansen, tglx,
	cmetcalf, slaoub, mst, akpm, hpa, ray.huang, paul.gortmaker,
	brgerst, adrian.hunter, colin.king, bp, lstoakes, qiaowei.ren,
	adam.buchbinder, keescook, jslaby, shuah, dvlasenk, mhiramat,
	luto, torvalds, pbonzini, peterz, acme, bp,
	ricardo.neri-calderon, thgarnie, ravi.v.shankar, linux-kernel,
	corbet

Commit-ID:  70e57c0f4b502f2435b7649a201861fe212c2e4e
Gitweb:     https://git.kernel.org/tip/70e57c0f4b502f2435b7649a201861fe212c2e4e
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:46 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:18 +0100

x86/insn-eval: Compute linear address in several utility functions

Computing a linear address involves several steps. The first step is to
compute the effective address. This requires determining the addressing
mode in use and perform arithmetic operations on the operands. Plus, each
addressing mode has special cases that must be handled.

Once the effective address is known, the base address of the applicable
segment is added to obtain the linear address.

Clearly, this is too much work for a single function. Instead, handle each
addressing mode in a separate utility function. This improves readability
and gives us the opportunity to handler errors better.

At the moment, arithmetic to compute the effective address uses 64-byte
variables. Thus, limit support to 64-bit addresses.

While reworking the function insn_get_addr_ref(), the variable addr_offset
is renamed as regoff to reflect its actual use (i.e., offset, from the
base of pt_regs, of the register used as operand).

Suggested-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Colin Ian King <colin.king@canonical.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-2-git-send-email-ricardo.neri-calderon@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/lib/insn-eval.c | 243 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 185 insertions(+), 58 deletions(-)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index 91f08aa..a4427b4 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -776,6 +776,182 @@ static int get_seg_base_limit(struct insn *insn, struct pt_regs *regs,
 	return 0;
 }
 
+/**
+ * get_eff_addr_reg() - Obtain effective address from register operand
+ * @insn:	Instruction. Must be valid.
+ * @regs:	Register values as seen when entering kernel mode
+ * @regoff:	Obtained operand offset, in pt_regs, with the effective address
+ * @eff_addr:	Obtained effective address
+ *
+ * Obtain the effective address stored in the register operand as indicated by
+ * the ModRM byte. This function is to be used only with register addressing
+ * (i.e.,  ModRM.mod is 3). The effective address is saved in @eff_addr. The
+ * register operand, as an offset from the base of pt_regs, is saved in @regoff;
+ * such offset can then be used to resolve the segment associated with the
+ * operand. This function can be used with any of the supported address sizes
+ * in x86.
+ *
+ * Returns:
+ *
+ * 0 on success. @eff_addr will have the effective address stored in the
+ * operand indicated by ModRM. @regoff will have such operand as an offset from
+ * the base of pt_regs.
+ *
+ * -EINVAL on error.
+ */
+static int get_eff_addr_reg(struct insn *insn, struct pt_regs *regs,
+			    int *regoff, long *eff_addr)
+{
+	insn_get_modrm(insn);
+
+	if (!insn->modrm.nbytes)
+		return -EINVAL;
+
+	if (X86_MODRM_MOD(insn->modrm.value) != 3)
+		return -EINVAL;
+
+	*regoff = get_reg_offset(insn, regs, REG_TYPE_RM);
+	if (*regoff < 0)
+		return -EINVAL;
+
+	*eff_addr = regs_get_register(regs, *regoff);
+
+	return 0;
+}
+
+/**
+ * get_eff_addr_modrm() - Obtain referenced effective address via ModRM
+ * @insn:	Instruction. Must be valid.
+ * @regs:	Register values as seen when entering kernel mode
+ * @regoff:	Obtained operand offset, in pt_regs, associated with segment
+ * @eff_addr:	Obtained effective address
+ *
+ * Obtain the effective address referenced by the ModRM byte of @insn. After
+ * identifying the registers involved in the register-indirect memory reference,
+ * its value is obtained from the operands in @regs. The computed address is
+ * stored @eff_addr. Also, the register operand that indicates the associated
+ * segment is stored in @regoff, this parameter can later be used to determine
+ * such segment.
+ *
+ * Returns:
+ *
+ * 0 on success. @eff_addr will have the referenced effective address. @regoff
+ * will have a register, as an offset from the base of pt_regs, that can be used
+ * to resolve the associated segment.
+ *
+ * -EINVAL on error.
+ */
+static int get_eff_addr_modrm(struct insn *insn, struct pt_regs *regs,
+			      int *regoff, long *eff_addr)
+{
+	long tmp;
+
+	if (insn->addr_bytes != 8)
+		return -EINVAL;
+
+	insn_get_modrm(insn);
+
+	if (!insn->modrm.nbytes)
+		return -EINVAL;
+
+	if (X86_MODRM_MOD(insn->modrm.value) > 2)
+		return -EINVAL;
+
+	*regoff = get_reg_offset(insn, regs, REG_TYPE_RM);
+
+	/*
+	 * -EDOM means that we must ignore the address_offset. In such a case,
+	 * in 64-bit mode the effective address relative to the rIP of the
+	 * following instruction.
+	 */
+	if (*regoff == -EDOM) {
+		if (user_64bit_mode(regs))
+			tmp = regs->ip + insn->length;
+		else
+			tmp = 0;
+	} else if (*regoff < 0) {
+		return -EINVAL;
+	} else {
+		tmp = regs_get_register(regs, *regoff);
+	}
+
+	*eff_addr = tmp + insn->displacement.value;
+
+	return 0;
+}
+
+/**
+ * get_eff_addr_sib() - Obtain referenced effective address via SIB
+ * @insn:	Instruction. Must be valid.
+ * @regs:	Register values as seen when entering kernel mode
+ * @regoff:	Obtained operand offset, in pt_regs, associated with segment
+ * @eff_addr:	Obtained effective address
+ *
+ * Obtain the effective address referenced by the SIB byte of @insn. After
+ * identifying the registers involved in the indexed, register-indirect memory
+ * reference, its value is obtained from the operands in @regs. The computed
+ * address is stored @eff_addr. Also, the register operand that indicates the
+ * associated segment is stored in @regoff, this parameter can later be used to
+ * determine such segment.
+ *
+ * Returns:
+ *
+ * 0 on success. @eff_addr will have the referenced effective address.
+ * @base_offset will have a register, as an offset from the base of pt_regs,
+ * that can be used to resolve the associated segment.
+ *
+ * -EINVAL on error.
+ */
+static int get_eff_addr_sib(struct insn *insn, struct pt_regs *regs,
+			    int *base_offset, long *eff_addr)
+{
+	long base, indx;
+	int indx_offset;
+
+	if (insn->addr_bytes != 8)
+		return -EINVAL;
+
+	insn_get_modrm(insn);
+
+	if (!insn->modrm.nbytes)
+		return -EINVAL;
+
+	if (X86_MODRM_MOD(insn->modrm.value) > 2)
+		return -EINVAL;
+
+	insn_get_sib(insn);
+
+	if (!insn->sib.nbytes)
+		return -EINVAL;
+
+	*base_offset = get_reg_offset(insn, regs, REG_TYPE_BASE);
+	indx_offset = get_reg_offset(insn, regs, REG_TYPE_INDEX);
+
+	/*
+	 * Negative values in the base and index offset means an error when
+	 * decoding the SIB byte. Except -EDOM, which means that the registers
+	 * should not be used in the address computation.
+	 */
+	if (*base_offset == -EDOM)
+		base = 0;
+	else if (*base_offset < 0)
+		return -EINVAL;
+	else
+		base = regs_get_register(regs, *base_offset);
+
+	if (indx_offset == -EDOM)
+		indx = 0;
+	else if (indx_offset < 0)
+		return -EINVAL;
+	else
+		indx = regs_get_register(regs, indx_offset);
+
+	*eff_addr = base + indx * (1 << X86_SIB_SCALE(insn->sib.value));
+
+	*eff_addr += insn->displacement.value;
+
+	return 0;
+}
 /*
  * return the address being referenced be instruction
  * for rm=3 returning the content of the rm reg
@@ -783,78 +959,29 @@ static int get_seg_base_limit(struct insn *insn, struct pt_regs *regs,
  */
 void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 {
-	int addr_offset, base_offset, indx_offset, ret;
 	unsigned long linear_addr = -1L, seg_base;
-	long eff_addr, base, indx;
-	insn_byte_t sib;
-
-	insn_get_modrm(insn);
-	insn_get_sib(insn);
-	sib = insn->sib.value;
+	int regoff, ret;
+	long eff_addr;
 
 	if (X86_MODRM_MOD(insn->modrm.value) == 3) {
-		addr_offset = get_reg_offset(insn, regs, REG_TYPE_RM);
-		if (addr_offset < 0)
+		ret = get_eff_addr_reg(insn, regs, &regoff, &eff_addr);
+		if (ret)
 			goto out;
 
-		eff_addr = regs_get_register(regs, addr_offset);
-
 	} else {
 		if (insn->sib.nbytes) {
-			/*
-			 * Negative values in the base and index offset means
-			 * an error when decoding the SIB byte. Except -EDOM,
-			 * which means that the registers should not be used
-			 * in the address computation.
-			 */
-			base_offset = get_reg_offset(insn, regs, REG_TYPE_BASE);
-			if (base_offset == -EDOM)
-				base = 0;
-			else if (base_offset < 0)
+			ret = get_eff_addr_sib(insn, regs, &regoff, &eff_addr);
+			if (ret)
 				goto out;
-			else
-				base = regs_get_register(regs, base_offset);
-
-			indx_offset = get_reg_offset(insn, regs, REG_TYPE_INDEX);
-
-			if (indx_offset == -EDOM)
-				indx = 0;
-			else if (indx_offset < 0)
-				goto out;
-			else
-				indx = regs_get_register(regs, indx_offset);
-
-			eff_addr = base + indx * (1 << X86_SIB_SCALE(sib));
-
-			/*
-			 * The base determines the segment used to compute
-			 * the linear address.
-			 */
-			addr_offset = base_offset;
-
 		} else {
-			addr_offset = get_reg_offset(insn, regs, REG_TYPE_RM);
-			/*
-			 * -EDOM means that we must ignore the address_offset.
-			 * In such a case, in 64-bit mode the effective address
-			 * relative to the RIP of the following instruction.
-			 */
-			if (addr_offset == -EDOM) {
-				if (user_64bit_mode(regs))
-					eff_addr = (long)regs->ip + insn->length;
-				else
-					eff_addr = 0;
-			} else if (addr_offset < 0) {
+			ret = get_eff_addr_modrm(insn, regs, &regoff, &eff_addr);
+			if (ret)
 				goto out;
-			} else {
-				eff_addr = regs_get_register(regs, addr_offset);
-			}
 		}
 
-		eff_addr += insn->displacement.value;
 	}
 
-	ret = get_seg_base_limit(insn, regs, addr_offset, &seg_base, NULL);
+	ret = get_seg_base_limit(insn, regs, regoff, &seg_base, NULL);
 	if (ret)
 		goto out;
 

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [tip:x86/asm] x86/insn-eval: Add support to resolve 32-bit address encodings
  2017-11-06  2:27 ` [PATCH v11 02/12] x86/insn-eval: Add support to resolve 32-bit address encodings Ricardo Neri
@ 2017-11-08 10:58   ` tip-bot for Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 10:58 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: dave.hansen, keescook, lstoakes, thgarnie, jslaby, brgerst,
	ray.huang, peterz, adam.buchbinder, tony.luck, dvyukov, dvlasenk,
	slaoub, qiaowei.ren, ricardo.neri-calderon, akpm, vbabka,
	ravi.v.shankar, luto, mingo, tglx, corbet, mhiramat,
	paul.gortmaker, cmetcalf, pbonzini, bp, acme, hpa, colin.king,
	mst, adrian.hunter, linux-kernel, shuah, torvalds, jpoimboe, bp

Commit-ID:  7a6daf79123a086f03b8cdfbc953958c8e1c1287
Gitweb:     https://git.kernel.org/tip/7a6daf79123a086f03b8cdfbc953958c8e1c1287
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:47 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:19 +0100

x86/insn-eval: Add support to resolve 32-bit address encodings

32-bit and 64-bit address encodings are identical. Thus, the same logic
could be used to resolve the effective address. However, there are two key
differences: address size and enforcement of segment limits.

If running a 32-bit process on a 64-bit kernel, it is best to perform
the address calculation using 32-bit data types. In this manner hardware
is used for the arithmetic, including handling of signs and overflows.

32-bit addresses are generally used in protected mode; segment limits are
enforced in this mode. This implementation obtains the limit of the
segment associated with the instruction operands and prefixes. If the
computed address is outside the segment limits, an error is returned. It
is also possible to use 32-bit address in long mode and virtual-8086 mode
by using an address override prefix. In such cases, segment limits are not
enforced.

Support to use 32-bit arithmetic is added to the utility functions that
compute effective addresses. However, the end result is stored in a
variable of type long (which has a width of 8 bytes in 64-bit builds).
Hence, once a 32-bit effective address is computed, the 4 most significant
bytes are masked out to avoid sign extension.

The newly added function get_addr_ref_32() is almost identical to the
existing function insn_get_addr_ref() (used for 64-bit addresses). The only
difference is that it verifies that the effective address is within the
limits of the segment.

Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Colin Ian King <colin.king@canonical.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-3-git-send-email-ricardo.neri-calderon@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/lib/insn-eval.c | 112 ++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 106 insertions(+), 6 deletions(-)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index a4427b4..e6cb68a 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -814,7 +814,11 @@ static int get_eff_addr_reg(struct insn *insn, struct pt_regs *regs,
 	if (*regoff < 0)
 		return -EINVAL;
 
-	*eff_addr = regs_get_register(regs, *regoff);
+	/* Ignore bytes that are outside the address size. */
+	if (insn->addr_bytes == 4)
+		*eff_addr = regs_get_register(regs, *regoff) & 0xffffffff;
+	else /* 64-bit address */
+		*eff_addr = regs_get_register(regs, *regoff);
 
 	return 0;
 }
@@ -846,7 +850,7 @@ static int get_eff_addr_modrm(struct insn *insn, struct pt_regs *regs,
 {
 	long tmp;
 
-	if (insn->addr_bytes != 8)
+	if (insn->addr_bytes != 8 && insn->addr_bytes != 4)
 		return -EINVAL;
 
 	insn_get_modrm(insn);
@@ -875,7 +879,13 @@ static int get_eff_addr_modrm(struct insn *insn, struct pt_regs *regs,
 		tmp = regs_get_register(regs, *regoff);
 	}
 
-	*eff_addr = tmp + insn->displacement.value;
+	if (insn->addr_bytes == 4) {
+		int addr32 = (int)(tmp & 0xffffffff) + insn->displacement.value;
+
+		*eff_addr = addr32 & 0xffffffff;
+	} else {
+		*eff_addr = tmp + insn->displacement.value;
+	}
 
 	return 0;
 }
@@ -908,7 +918,7 @@ static int get_eff_addr_sib(struct insn *insn, struct pt_regs *regs,
 	long base, indx;
 	int indx_offset;
 
-	if (insn->addr_bytes != 8)
+	if (insn->addr_bytes != 8 && insn->addr_bytes != 4)
 		return -EINVAL;
 
 	insn_get_modrm(insn);
@@ -946,12 +956,102 @@ static int get_eff_addr_sib(struct insn *insn, struct pt_regs *regs,
 	else
 		indx = regs_get_register(regs, indx_offset);
 
-	*eff_addr = base + indx * (1 << X86_SIB_SCALE(insn->sib.value));
+	if (insn->addr_bytes == 4) {
+		int addr32, base32, idx32;
+
+		base32 = base & 0xffffffff;
+		idx32 = indx & 0xffffffff;
 
-	*eff_addr += insn->displacement.value;
+		addr32 = base32 + idx32 * (1 << X86_SIB_SCALE(insn->sib.value));
+		addr32 += insn->displacement.value;
+
+		*eff_addr = addr32 & 0xffffffff;
+	} else {
+		*eff_addr = base + indx * (1 << X86_SIB_SCALE(insn->sib.value));
+		*eff_addr += insn->displacement.value;
+	}
 
 	return 0;
 }
+
+/**
+ * get_addr_ref_32() - Obtain a 32-bit linear address
+ * @insn:	Instruction with ModRM, SIB bytes and displacement
+ * @regs:	Register values as seen when entering kernel mode
+ *
+ * This function is to be used with 32-bit address encodings to obtain the
+ * linear memory address referred by the instruction's ModRM, SIB,
+ * displacement bytes and segment base address, as applicable. If in protected
+ * mode, segment limits are enforced.
+ *
+ * Returns:
+ *
+ * Linear address referenced by instruction and registers on success.
+ *
+ * -1L on error.
+ */
+static void __user *get_addr_ref_32(struct insn *insn, struct pt_regs *regs)
+{
+	unsigned long linear_addr = -1L, seg_base, seg_limit;
+	int eff_addr, regoff;
+	long tmp;
+	int ret;
+
+	if (insn->addr_bytes != 4)
+		goto out;
+
+	if (X86_MODRM_MOD(insn->modrm.value) == 3) {
+		ret = get_eff_addr_reg(insn, regs, &regoff, &tmp);
+		if (ret)
+			goto out;
+
+		eff_addr = tmp;
+
+	} else {
+		if (insn->sib.nbytes) {
+			ret = get_eff_addr_sib(insn, regs, &regoff, &tmp);
+			if (ret)
+				goto out;
+
+			eff_addr = tmp;
+		} else {
+			ret = get_eff_addr_modrm(insn, regs, &regoff, &tmp);
+			if (ret)
+				goto out;
+
+			eff_addr = tmp;
+		}
+	}
+
+	ret = get_seg_base_limit(insn, regs, regoff, &seg_base, &seg_limit);
+	if (ret)
+		goto out;
+
+	/*
+	 * In protected mode, before computing the linear address, make sure
+	 * the effective address is within the limits of the segment.
+	 * 32-bit addresses can be used in long and virtual-8086 modes if an
+	 * address override prefix is used. In such cases, segment limits are
+	 * not enforced. When in virtual-8086 mode, the segment limit is -1L
+	 * to reflect this situation.
+	 *
+	 * After computed, the effective address is treated as an unsigned
+	 * quantity.
+	 */
+	if (!user_64bit_mode(regs) && ((unsigned int)eff_addr > seg_limit))
+		goto out;
+
+	/*
+	 * Data type long could be 64 bits in size. Ensure that our 32-bit
+	 * effective address is not sign-extended when computing the linear
+	 * address.
+	 */
+	linear_addr = (unsigned long)(eff_addr & 0xffffffff) + seg_base;
+
+out:
+	return (void __user *)linear_addr;
+}
+
 /*
  * return the address being referenced be instruction
  * for rm=3 returning the content of the rm reg

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [tip:x86/asm] x86/insn-eval: Add wrapper function for 32 and 64-bit addresses
  2017-11-06  2:27 ` [PATCH v11 03/12] x86/insn-eval: Add wrapper function for 32 and 64-bit addresses Ricardo Neri
@ 2017-11-08 10:58   ` tip-bot for Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 10:58 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: bp, paul.gortmaker, adam.buchbinder, dvlasenk, peterz, mingo,
	hpa, ricardo.neri-calderon, tony.luck, ravi.v.shankar, pbonzini,
	shuah, vbabka, jslaby, adrian.hunter, dvyukov, colin.king, acme,
	lstoakes, slaoub, luto, torvalds, dave.hansen, mhiramat, mst,
	corbet, brgerst, keescook, bp, cmetcalf, ray.huang, jpoimboe,
	linux-kernel, thgarnie, qiaowei.ren, tglx, akpm

Commit-ID:  cd9b594a9ef122a41bc961c330a55d87e226822f
Gitweb:     https://git.kernel.org/tip/cd9b594a9ef122a41bc961c330a55d87e226822f
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:48 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:20 +0100

x86/insn-eval: Add wrapper function for 32 and 64-bit addresses

The function insn_get_addr_ref() is capable of handling only 64-bit
addresses. A previous commit introduced a function to handle 32-bit
addresses. Invoke these two functions from a third wrapper function that
calls the appropriate routine based on the address size specified in the
instruction structure (obtained by looking at the code segment default
address size and the address override prefix, if present).

While doing this, rename the original function insn_get_addr_ref() with
the more appropriate name get_addr_ref_64(), ensure it is only used
for 64-bit addresses.

Also, since 64-bit addresses are not possible in 32-bit builds, provide
a dummy function such case.

Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Colin Ian King <colin.king@canonical.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-4-git-send-email-ricardo.neri-calderon@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/lib/insn-eval.c | 60 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 55 insertions(+), 5 deletions(-)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index e6cb68a..1ac3973 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -1052,17 +1052,36 @@ out:
 	return (void __user *)linear_addr;
 }
 
-/*
- * return the address being referenced be instruction
- * for rm=3 returning the content of the rm reg
- * for rm!=3 calculates the address using SIB and Disp
+/**
+ * get_addr_ref_64() - Obtain a 64-bit linear address
+ * @insn:	Instruction struct with ModRM and SIB bytes and displacement
+ * @regs:	Structure with register values as seen when entering kernel mode
+ *
+ * This function is to be used with 64-bit address encodings to obtain the
+ * linear memory address referred by the instruction's ModRM, SIB,
+ * displacement bytes and segment base address, as applicable.
+ *
+ * Returns:
+ *
+ * Linear address referenced by instruction and registers on success.
+ *
+ * -1L on error.
  */
-void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
+#ifndef CONFIG_X86_64
+static void __user *get_addr_ref_64(struct insn *insn, struct pt_regs *regs)
+{
+	return (void __user *)-1L;
+}
+#else
+static void __user *get_addr_ref_64(struct insn *insn, struct pt_regs *regs)
 {
 	unsigned long linear_addr = -1L, seg_base;
 	int regoff, ret;
 	long eff_addr;
 
+	if (insn->addr_bytes != 8)
+		goto out;
+
 	if (X86_MODRM_MOD(insn->modrm.value) == 3) {
 		ret = get_eff_addr_reg(insn, regs, &regoff, &eff_addr);
 		if (ret)
@@ -1090,3 +1109,34 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 out:
 	return (void __user *)linear_addr;
 }
+#endif /* CONFIG_X86_64 */
+
+/**
+ * insn_get_addr_ref() - Obtain the linear address referred by instruction
+ * @insn:	Instruction structure containing ModRM byte and displacement
+ * @regs:	Structure with register values as seen when entering kernel mode
+ *
+ * Obtain the linear address referred by the instruction's ModRM, SIB and
+ * displacement bytes, and segment base, as applicable. In protected mode,
+ * segment limits are enforced.
+ *
+ * Returns:
+ *
+ * Linear address referenced by instruction and registers on success.
+ *
+ * -1L on error.
+ */
+void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
+{
+	if (!insn || !regs)
+		return (void __user *)-1L;
+
+	switch (insn->addr_bytes) {
+	case 4:
+		return get_addr_ref_32(insn, regs);
+	case 8:
+		return get_addr_ref_64(insn, regs);
+	default:
+		return (void __user *)-1L;
+	}
+}

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [tip:x86/asm] x86/insn-eval: Handle 32-bit address encodings in virtual-8086 mode
  2017-11-06  2:27 ` [PATCH v11 04/12] x86/insn-eval: Handle 32-bit address encodings in virtual-8086 mode Ricardo Neri
@ 2017-11-08 10:59   ` tip-bot for Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 10:59 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: adam.buchbinder, dvyukov, tony.luck, pbonzini, peterz, hpa,
	keescook, ray.huang, mhiramat, jpoimboe, linux-kernel, dvlasenk,
	shuah, cmetcalf, bp, qiaowei.ren, colin.king, slaoub, tglx,
	corbet, acme, jslaby, ravi.v.shankar, mingo,
	ricardo.neri-calderon, lstoakes, luto, brgerst, akpm,
	dave.hansen, torvalds, thgarnie, vbabka, mst, adrian.hunter,
	paul.gortmaker, bp

Commit-ID:  86cc35109029b7f1b195cef6c74654bad95e81af
Gitweb:     https://git.kernel.org/tip/86cc35109029b7f1b195cef6c74654bad95e81af
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:49 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:20 +0100

x86/insn-eval: Handle 32-bit address encodings in virtual-8086 mode

It is possible to utilize 32-bit address encodings in virtual-8086 mode via
an address override instruction prefix. However, the range of the
effective address is still limited to [0x-0xffff]. In such a case, return
error.

Also, linear addresses in virtual-8086 mode are limited to 20 bits. Enforce
such limit by truncating the most significant bytes of the computed linear
address.

Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Colin Ian King <colin.king@canonical.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-5-git-send-email-ricardo.neri-calderon@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/lib/insn-eval.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index 1ac3973..ef102db 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -1042,12 +1042,23 @@ static void __user *get_addr_ref_32(struct insn *insn, struct pt_regs *regs)
 		goto out;
 
 	/*
+	 * Even though 32-bit address encodings are allowed in virtual-8086
+	 * mode, the address range is still limited to [0x-0xffff].
+	 */
+	if (v8086_mode(regs) && (eff_addr & ~0xffff))
+		goto out;
+
+	/*
 	 * Data type long could be 64 bits in size. Ensure that our 32-bit
 	 * effective address is not sign-extended when computing the linear
 	 * address.
 	 */
 	linear_addr = (unsigned long)(eff_addr & 0xffffffff) + seg_base;
 
+	/* Limit linear address to 20 bits */
+	if (v8086_mode(regs))
+		linear_addr &= 0xfffff;
+
 out:
 	return (void __user *)linear_addr;
 }

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [tip:x86/asm] x86/insn-eval: Add support to resolve 16-bit address encodings
  2017-11-06  2:27 ` [PATCH v11 05/12] x86/insn-eval: Add support to resolve 16-bit address encodings Ricardo Neri
@ 2017-11-08 10:59   ` tip-bot for Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 10:59 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: shuah, torvalds, thgarnie, corbet, keescook, ray.huang, tglx,
	qiaowei.ren, linux-kernel, cmetcalf, akpm, luto, lstoakes,
	jslaby, peterz, colin.king, dave.hansen, acme, vbabka,
	ricardo.neri-calderon, hpa, ravi.v.shankar, mst, pbonzini,
	adrian.hunter, bp, mingo, adam.buchbinder, brgerst, dvlasenk,
	tony.luck, dvyukov, bp, mhiramat, jpoimboe, paul.gortmaker,
	slaoub

Commit-ID:  9c6c799faeed54b17857c2eed9058a25b8ee3614
Gitweb:     https://git.kernel.org/tip/9c6c799faeed54b17857c2eed9058a25b8ee3614
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:50 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:20 +0100

x86/insn-eval: Add support to resolve 16-bit address encodings

Tasks running in virtual-8086 mode, in protected mode with code segment
descriptors that specify 16-bit default address sizes via the D bit, or via
an address override prefix will use 16-bit addressing form encodings as
described in the Intel 64 and IA-32 Architecture Software Developer's
Manual Volume 2A Section 2.1.5, Table 2-1.

16-bit addressing encodings differ in several ways from the 32-bit/64-bit
addressing form encodings: ModRM.rm points to different registers and, in
some cases, effective addresses are indicated by the addition of the value
of two registers. Also, there is no support for SIB bytes. Thus, a
separate function is needed to parse this form of addressing.

Three functions are introduced. get_reg_offset_16() obtains the
offset from the base of pt_regs of the registers indicated by the ModRM
byte of the address encoding. get_eff_addr_modrm_16() computes the
effective address from the value of the register operands.
get_addr_ref_16() computes the linear address using the obtained effective
address and the base address of the segment.

Segment limits are enforced when running in protected mode.

Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Colin Ian King <colin.king@canonical.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Qiaowei Ren <qiaowei.ren@intel.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-6-git-send-email-ricardo.neri-calderon@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/lib/insn-eval.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 212 insertions(+), 1 deletion(-)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index ef102db..35625d2 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -481,6 +481,80 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
 }
 
 /**
+ * get_reg_offset_16() - Obtain offset of register indicated by instruction
+ * @insn:	Instruction containing ModRM byte
+ * @regs:	Register values as seen when entering kernel mode
+ * @offs1:	Offset of the first operand register
+ * @offs2:	Offset of the second opeand register, if applicable
+ *
+ * Obtain the offset, in pt_regs, of the registers indicated by the ModRM byte
+ * in @insn. This function is to be used with 16-bit address encodings. The
+ * @offs1 and @offs2 will be written with the offset of the two registers
+ * indicated by the instruction. In cases where any of the registers is not
+ * referenced by the instruction, the value will be set to -EDOM.
+ *
+ * Returns:
+ *
+ * 0 on success, -EINVAL on error.
+ */
+static int get_reg_offset_16(struct insn *insn, struct pt_regs *regs,
+			     int *offs1, int *offs2)
+{
+	/*
+	 * 16-bit addressing can use one or two registers. Specifics of
+	 * encodings are given in Table 2-1. "16-Bit Addressing Forms with the
+	 * ModR/M Byte" of the Intel Software Development Manual.
+	 */
+	static const int regoff1[] = {
+		offsetof(struct pt_regs, bx),
+		offsetof(struct pt_regs, bx),
+		offsetof(struct pt_regs, bp),
+		offsetof(struct pt_regs, bp),
+		offsetof(struct pt_regs, si),
+		offsetof(struct pt_regs, di),
+		offsetof(struct pt_regs, bp),
+		offsetof(struct pt_regs, bx),
+	};
+
+	static const int regoff2[] = {
+		offsetof(struct pt_regs, si),
+		offsetof(struct pt_regs, di),
+		offsetof(struct pt_regs, si),
+		offsetof(struct pt_regs, di),
+		-EDOM,
+		-EDOM,
+		-EDOM,
+		-EDOM,
+	};
+
+	if (!offs1 || !offs2)
+		return -EINVAL;
+
+	/* Operand is a register, use the generic function. */
+	if (X86_MODRM_MOD(insn->modrm.value) == 3) {
+		*offs1 = insn_get_modrm_rm_off(insn, regs);
+		*offs2 = -EDOM;
+		return 0;
+	}
+
+	*offs1 = regoff1[X86_MODRM_RM(insn->modrm.value)];
+	*offs2 = regoff2[X86_MODRM_RM(insn->modrm.value)];
+
+	/*
+	 * If ModRM.mod is 0 and ModRM.rm is 110b, then we use displacement-
+	 * only addressing. This means that no registers are involved in
+	 * computing the effective address. Thus, ensure that the first
+	 * register offset is invalild. The second register offset is already
+	 * invalid under the aforementioned conditions.
+	 */
+	if ((X86_MODRM_MOD(insn->modrm.value) == 0) &&
+	    (X86_MODRM_RM(insn->modrm.value) == 6))
+		*offs1 = -EDOM;
+
+	return 0;
+}
+
+/**
  * get_desc() - Obtain pointer to a segment descriptor
  * @sel:	Segment selector
  *
@@ -815,7 +889,9 @@ static int get_eff_addr_reg(struct insn *insn, struct pt_regs *regs,
 		return -EINVAL;
 
 	/* Ignore bytes that are outside the address size. */
-	if (insn->addr_bytes == 4)
+	if (insn->addr_bytes == 2)
+		*eff_addr = regs_get_register(regs, *regoff) & 0xffff;
+	else if (insn->addr_bytes == 4)
 		*eff_addr = regs_get_register(regs, *regoff) & 0xffffffff;
 	else /* 64-bit address */
 		*eff_addr = regs_get_register(regs, *regoff);
@@ -891,6 +967,74 @@ static int get_eff_addr_modrm(struct insn *insn, struct pt_regs *regs,
 }
 
 /**
+ * get_eff_addr_modrm_16() - Obtain referenced effective address via ModRM
+ * @insn:	Instruction. Must be valid.
+ * @regs:	Register values as seen when entering kernel mode
+ * @regoff:	Obtained operand offset, in pt_regs, associated with segment
+ * @eff_addr:	Obtained effective address
+ *
+ * Obtain the 16-bit effective address referenced by the ModRM byte of @insn.
+ * After identifying the registers involved in the register-indirect memory
+ * reference, its value is obtained from the operands in @regs. The computed
+ * address is stored @eff_addr. Also, the register operand that indicates
+ * the associated segment is stored in @regoff, this parameter can later be used
+ * to determine such segment.
+ *
+ * Returns:
+ *
+ * 0 on success. @eff_addr will have the referenced effective address. @regoff
+ * will have a register, as an offset from the base of pt_regs, that can be used
+ * to resolve the associated segment.
+ *
+ * -EINVAL on error.
+ */
+static int get_eff_addr_modrm_16(struct insn *insn, struct pt_regs *regs,
+				 int *regoff, short *eff_addr)
+{
+	int addr_offset1, addr_offset2, ret;
+	short addr1 = 0, addr2 = 0, displacement;
+
+	if (insn->addr_bytes != 2)
+		return -EINVAL;
+
+	insn_get_modrm(insn);
+
+	if (!insn->modrm.nbytes)
+		return -EINVAL;
+
+	if (X86_MODRM_MOD(insn->modrm.value) > 2)
+		return -EINVAL;
+
+	ret = get_reg_offset_16(insn, regs, &addr_offset1, &addr_offset2);
+	if (ret < 0)
+		return -EINVAL;
+
+	/*
+	 * Don't fail on invalid offset values. They might be invalid because
+	 * they cannot be used for this particular value of ModRM. Instead, use
+	 * them in the computation only if they contain a valid value.
+	 */
+	if (addr_offset1 != -EDOM)
+		addr1 = regs_get_register(regs, addr_offset1) & 0xffff;
+
+	if (addr_offset2 != -EDOM)
+		addr2 = regs_get_register(regs, addr_offset2) & 0xffff;
+
+	displacement = insn->displacement.value & 0xffff;
+	*eff_addr = addr1 + addr2 + displacement;
+
+	/*
+	 * The first operand register could indicate to use of either SS or DS
+	 * registers to obtain the segment selector.  The second operand
+	 * register can only indicate the use of DS. Thus, the first operand
+	 * will be used to obtain the segment selector.
+	 */
+	*regoff = addr_offset1;
+
+	return 0;
+}
+
+/**
  * get_eff_addr_sib() - Obtain referenced effective address via SIB
  * @insn:	Instruction. Must be valid.
  * @regs:	Register values as seen when entering kernel mode
@@ -975,6 +1119,71 @@ static int get_eff_addr_sib(struct insn *insn, struct pt_regs *regs,
 }
 
 /**
+ * get_addr_ref_16() - Obtain the 16-bit address referred by instruction
+ * @insn:	Instruction containing ModRM byte and displacement
+ * @regs:	Register values as seen when entering kernel mode
+ *
+ * This function is to be used with 16-bit address encodings. Obtain the memory
+ * address referred by the instruction's ModRM and displacement bytes. Also, the
+ * segment used as base is determined by either any segment override prefixes in
+ * @insn or the default segment of the registers involved in the address
+ * computation. In protected mode, segment limits are enforced.
+ *
+ * Returns:
+ *
+ * Linear address referenced by the instruction operands on success.
+ *
+ * -1L on error.
+ */
+static void __user *get_addr_ref_16(struct insn *insn, struct pt_regs *regs)
+{
+	unsigned long linear_addr = -1L, seg_base, seg_limit;
+	int ret, regoff;
+	short eff_addr;
+	long tmp;
+
+	insn_get_modrm(insn);
+	insn_get_displacement(insn);
+
+	if (insn->addr_bytes != 2)
+		goto out;
+
+	if (X86_MODRM_MOD(insn->modrm.value) == 3) {
+		ret = get_eff_addr_reg(insn, regs, &regoff, &tmp);
+		if (ret)
+			goto out;
+
+		eff_addr = tmp;
+	} else {
+		ret = get_eff_addr_modrm_16(insn, regs, &regoff, &eff_addr);
+		if (ret)
+			goto out;
+	}
+
+	ret = get_seg_base_limit(insn, regs, regoff, &seg_base, &seg_limit);
+	if (ret)
+		goto out;
+
+	/*
+	 * Before computing the linear address, make sure the effective address
+	 * is within the limits of the segment. In virtual-8086 mode, segment
+	 * limits are not enforced. In such a case, the segment limit is -1L to
+	 * reflect this fact.
+	 */
+	if ((unsigned long)(eff_addr & 0xffff) > seg_limit)
+		goto out;
+
+	linear_addr = (unsigned long)(eff_addr & 0xffff) + seg_base;
+
+	/* Limit linear address to 20 bits */
+	if (v8086_mode(regs))
+		linear_addr &= 0xfffff;
+
+out:
+	return (void __user *)linear_addr;
+}
+
+/**
  * get_addr_ref_32() - Obtain a 32-bit linear address
  * @insn:	Instruction with ModRM, SIB bytes and displacement
  * @regs:	Register values as seen when entering kernel mode
@@ -1143,6 +1352,8 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 		return (void __user *)-1L;
 
 	switch (insn->addr_bytes) {
+	case 2:
+		return get_addr_ref_16(insn, regs);
 	case 4:
 		return get_addr_ref_32(insn, regs);
 	case 8:

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [tip:x86/asm] x86/cpufeature: Add User-Mode Instruction Prevention definitions
  2017-11-06  2:27 ` [PATCH v11 06/12] x86/cpufeature: Add User-Mode Instruction Prevention definitions Ricardo Neri
@ 2017-11-08 10:59   ` tip-bot for Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 10:59 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: luto, torvalds, shuah, bp, linux-kernel, mst, mingo, bp, brgerst,
	vbabka, paul.gortmaker, ravi.v.shankar, dvlasenk, fenghua.yu,
	slaoub, cmetcalf, ray.huang, mhiramat, jpoimboe, peterz, akpm,
	dave.hansen, tony.luck, pbonzini, tglx, jslaby, corbet, hpa,
	ricardo.neri-calderon

Commit-ID:  3522c2a6a4f341058b8291326a945e2a2d2aaf55
Gitweb:     https://git.kernel.org/tip/3522c2a6a4f341058b8291326a945e2a2d2aaf55
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:51 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:21 +0100

x86/cpufeature: Add User-Mode Instruction Prevention definitions

User-Mode Instruction Prevention is a security feature present in new
Intel processors that, when set, prevents the execution of a subset of
instructions if such instructions are executed in user mode (CPL > 0).
Attempting to execute such instructions causes a general protection
exception.

The subset of instructions comprises:

 * SGDT - Store Global Descriptor Table
 * SIDT - Store Interrupt Descriptor Table
 * SLDT - Store Local Descriptor Table
 * SMSW - Store Machine Status Word
 * STR  - Store Task Register

This feature is also added to the list of disabled-features to allow
a cleaner handling of build-time configuration.

Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Borislav Petkov <bp@suse.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-7-git-send-email-ricardo.neri-calderon@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/include/asm/cpufeatures.h          | 1 +
 arch/x86/include/asm/disabled-features.h    | 8 +++++++-
 arch/x86/include/uapi/asm/processor-flags.h | 2 ++
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index cdf5be8..c0b0e9e 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -296,6 +296,7 @@
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ECX), word 16 */
 #define X86_FEATURE_AVX512VBMI		(16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
+#define X86_FEATURE_UMIP		(16*32+ 2) /* User Mode Instruction Protection */
 #define X86_FEATURE_PKU			(16*32+ 3) /* Protection Keys for Userspace */
 #define X86_FEATURE_OSPKE		(16*32+ 4) /* OS Protection Keys Enable */
 #define X86_FEATURE_AVX512_VBMI2	(16*32+ 6) /* Additional AVX512 Vector Bit Manipulation Instructions */
diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
index c10c912..14d6d50 100644
--- a/arch/x86/include/asm/disabled-features.h
+++ b/arch/x86/include/asm/disabled-features.h
@@ -16,6 +16,12 @@
 # define DISABLE_MPX	(1<<(X86_FEATURE_MPX & 31))
 #endif
 
+#ifdef CONFIG_X86_INTEL_UMIP
+# define DISABLE_UMIP	0
+#else
+# define DISABLE_UMIP	(1<<(X86_FEATURE_UMIP & 31))
+#endif
+
 #ifdef CONFIG_X86_64
 # define DISABLE_VME		(1<<(X86_FEATURE_VME & 31))
 # define DISABLE_K6_MTRR	(1<<(X86_FEATURE_K6_MTRR & 31))
@@ -63,7 +69,7 @@
 #define DISABLED_MASK13	0
 #define DISABLED_MASK14	0
 #define DISABLED_MASK15	0
-#define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57)
+#define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57|DISABLE_UMIP)
 #define DISABLED_MASK17	0
 #define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
 
diff --git a/arch/x86/include/uapi/asm/processor-flags.h b/arch/x86/include/uapi/asm/processor-flags.h
index 53b4ca5..7e1e730 100644
--- a/arch/x86/include/uapi/asm/processor-flags.h
+++ b/arch/x86/include/uapi/asm/processor-flags.h
@@ -105,6 +105,8 @@
 #define X86_CR4_OSFXSR		_BITUL(X86_CR4_OSFXSR_BIT)
 #define X86_CR4_OSXMMEXCPT_BIT	10 /* enable unmasked SSE exceptions */
 #define X86_CR4_OSXMMEXCPT	_BITUL(X86_CR4_OSXMMEXCPT_BIT)
+#define X86_CR4_UMIP_BIT	11 /* enable UMIP support */
+#define X86_CR4_UMIP		_BITUL(X86_CR4_UMIP_BIT)
 #define X86_CR4_LA57_BIT	12 /* enable 5-level page tables */
 #define X86_CR4_LA57		_BITUL(X86_CR4_LA57_BIT)
 #define X86_CR4_VMXE_BIT	13 /* enable VMX virtualization */

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-06  2:27 ` [PATCH v11 07/12] x86: Add emulation code for UMIP instructions Ricardo Neri
@ 2017-11-08 11:00   ` tip-bot for Ricardo Neri
  2017-11-08 16:14     ` Denys Vlasenko
  0 siblings, 1 reply; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 11:00 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, mst, luto, dave.hansen, ray.huang, mhiramat, tglx,
	jslaby, shuah, mingo, slaoub, peterz, bp, tony.luck, jpoimboe,
	fenghua.yu, dvlasenk, hpa, bp, vbabka, pbonzini, paul.gortmaker,
	akpm, torvalds, ricardo.neri-calderon, cmetcalf, ravi.v.shankar,
	corbet, brgerst

Commit-ID:  1e5db223696afa55e6a038fac638f759e1fdcc01
Gitweb:     https://git.kernel.org/tip/1e5db223696afa55e6a038fac638f759e1fdcc01
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:52 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:22 +0100

x86/umip: Add emulation code for UMIP instructions

The feature User-Mode Instruction Prevention present in recent Intel
processor prevents a group of instructions (sgdt, sidt, sldt, smsw, and
str) from being executed with CPL > 0. Otherwise, a general protection
fault is issued.

Rather than relaying to the user space the general protection fault caused
by the UMIP-protected instructions (in the form of a SIGSEGV signal), it
can be trapped and the instruction emulated to provide a dummy result.
This allows to both conserve the current kernel behavior and not reveal the
system resources that UMIP intends to protect (i.e., the locations of the
global descriptor and interrupt descriptor tables, the segment selectors of
the local descriptor table, the value of the task state register and the
contents of the CR0 register).

This emulation is needed because certain applications (e.g., WineHQ and
DOSEMU2) rely on this subset of instructions to function. Given that sldt
and str are not commonly used in programs that run on WineHQ or DOSEMU2,
they are not emulated. Also, emulation is provided only for 32-bit
processes; 64-bit processes that attempt to use the instructions that UMIP
protects will receive the SIGSEGV signal issued as a consequence of the
general protection fault.

The instructions protected by UMIP can be split in two groups. Those which
return a kernel memory address (sgdt and sidt) and those which return a
value (smsw, sldt and str; the last two not emulated).

For the instructions that return a kernel memory address, applications such
as WineHQ rely on the result being located in the kernel memory space, not
the actual location of the table. The result is emulated as a hard-coded
value that lies close to the top of the kernel memory. The limit for the
GDT and the IDT are set to zero.

The instruction smsw is emulated to return the value that the register CR0
has at boot time as set in the head_32.

Care is taken to appropriately emulate the results when segmentation is
used. That is, rather than relying on USER_DS and USER_CS, the function
insn_get_addr_ref() inspects the segment descriptor pointed by the
registers in pt_regs. This ensures that we correctly obtain the segment
base address and the address and operand sizes even if the user space
application uses a local descriptor table.

Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-8-git-send-email-ricardo.neri-calderon@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/include/asm/umip.h |  12 ++
 arch/x86/kernel/Makefile    |   1 +
 arch/x86/kernel/umip.c      | 321 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 334 insertions(+)

diff --git a/arch/x86/include/asm/umip.h b/arch/x86/include/asm/umip.h
new file mode 100644
index 0000000..db43f2a
--- /dev/null
+++ b/arch/x86/include/asm/umip.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_X86_UMIP_H
+#define _ASM_X86_UMIP_H
+
+#include <linux/types.h>
+#include <asm/ptrace.h>
+
+#ifdef CONFIG_X86_INTEL_UMIP
+bool fixup_umip_exception(struct pt_regs *regs);
+#else
+static inline bool fixup_umip_exception(struct pt_regs *regs) { return false; }
+#endif  /* CONFIG_X86_INTEL_UMIP */
+#endif  /* _ASM_X86_UMIP_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 295abaa..81bb565 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -127,6 +127,7 @@ obj-$(CONFIG_EFI)			+= sysfb_efi.o
 obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 obj-$(CONFIG_TRACING)			+= tracepoint.o
 obj-$(CONFIG_SCHED_MC_PRIO)		+= itmt.o
+obj-$(CONFIG_X86_INTEL_UMIP)		+= umip.o
 
 obj-$(CONFIG_UNWINDER_ORC)		+= unwind_orc.o
 obj-$(CONFIG_UNWINDER_FRAME_POINTER)	+= unwind_frame.o
diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
new file mode 100644
index 0000000..d80b816
--- /dev/null
+++ b/arch/x86/kernel/umip.c
@@ -0,0 +1,321 @@
+/*
+ * umip.c Emulation for instruction protected by the Intel User-Mode
+ * Instruction Prevention feature
+ *
+ * Copyright (c) 2017, Intel Corporation.
+ * Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
+ */
+
+#include <linux/uaccess.h>
+#include <asm/umip.h>
+#include <asm/traps.h>
+#include <asm/insn.h>
+#include <asm/insn-eval.h>
+
+/** DOC: Emulation for User-Mode Instruction Prevention (UMIP)
+ *
+ * The feature User-Mode Instruction Prevention present in recent Intel
+ * processor prevents a group of instructions (sgdt, sidt, sldt, smsw, and str)
+ * from being executed with CPL > 0. Otherwise, a general protection fault is
+ * issued.
+ *
+ * Rather than relaying to the user space the general protection fault caused by
+ * the UMIP-protected instructions (in the form of a SIGSEGV signal), it can be
+ * trapped and emulate the result of such instructions to provide dummy values.
+ * This allows to both conserve the current kernel behavior and not reveal the
+ * system resources that UMIP intends to protect (i.e., the locations of the
+ * global descriptor and interrupt descriptor tables, the segment selectors of
+ * the local descriptor table, the value of the task state register and the
+ * contents of the CR0 register).
+ *
+ * This emulation is needed because certain applications (e.g., WineHQ and
+ * DOSEMU2) rely on this subset of instructions to function.
+ *
+ * The instructions protected by UMIP can be split in two groups. Those which
+ * return a kernel memory address (sgdt and sidt) and those which return a
+ * value (sldt, str and smsw).
+ *
+ * For the instructions that return a kernel memory address, applications
+ * such as WineHQ rely on the result being located in the kernel memory space,
+ * not the actual location of the table. The result is emulated as a hard-coded
+ * value that, lies close to the top of the kernel memory. The limit for the GDT
+ * and the IDT are set to zero.
+ *
+ * Given that sldt and str are not commonly used in programs that run on WineHQ
+ * or DOSEMU2, they are not emulated.
+ *
+ * The instruction smsw is emulated to return the value that the register CR0
+ * has at boot time as set in the head_32.
+ *
+ * Also, emulation is provided only for 32-bit processes; 64-bit processes
+ * that attempt to use the instructions that UMIP protects will receive the
+ * SIGSEGV signal issued as a consequence of the general protection fault.
+ *
+ * Care is taken to appropriately emulate the results when segmentation is
+ * used. That is, rather than relying on USER_DS and USER_CS, the function
+ * insn_get_addr_ref() inspects the segment descriptor pointed by the
+ * registers in pt_regs. This ensures that we correctly obtain the segment
+ * base address and the address and operand sizes even if the user space
+ * application uses a local descriptor table.
+ */
+
+#define UMIP_DUMMY_GDT_BASE 0xfffe0000
+#define UMIP_DUMMY_IDT_BASE 0xffff0000
+
+/*
+ * The SGDT and SIDT instructions store the contents of the global descriptor
+ * table and interrupt table registers, respectively. The destination is a
+ * memory operand of X+2 bytes. X bytes are used to store the base address of
+ * the table and 2 bytes are used to store the limit. In 32-bit processes, the
+ * only processes for which emulation is provided, X has a value of 4.
+ */
+#define UMIP_GDT_IDT_BASE_SIZE 4
+#define UMIP_GDT_IDT_LIMIT_SIZE 2
+
+#define	UMIP_INST_SGDT	0	/* 0F 01 /0 */
+#define	UMIP_INST_SIDT	1	/* 0F 01 /1 */
+#define	UMIP_INST_SMSW	3	/* 0F 01 /4 */
+
+/**
+ * identify_insn() - Identify a UMIP-protected instruction
+ * @insn:	Instruction structure with opcode and ModRM byte.
+ *
+ * From the opcode and ModRM.reg in @insn identify, if any, a UMIP-protected
+ * instruction that can be emulated.
+ *
+ * Returns:
+ *
+ * On success, a constant identifying a specific UMIP-protected instruction that
+ * can be emulated.
+ *
+ * -EINVAL on error or when not an UMIP-protected instruction that can be
+ * emulated.
+ */
+static int identify_insn(struct insn *insn)
+{
+	/* By getting modrm we also get the opcode. */
+	insn_get_modrm(insn);
+
+	if (!insn->modrm.nbytes)
+		return -EINVAL;
+
+	/* All the instructions of interest start with 0x0f. */
+	if (insn->opcode.bytes[0] != 0xf)
+		return -EINVAL;
+
+	if (insn->opcode.bytes[1] == 0x1) {
+		switch (X86_MODRM_REG(insn->modrm.value)) {
+		case 0:
+			return UMIP_INST_SGDT;
+		case 1:
+			return UMIP_INST_SIDT;
+		case 4:
+			return UMIP_INST_SMSW;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	/* SLDT AND STR are not emulated */
+	return -EINVAL;
+}
+
+/**
+ * emulate_umip_insn() - Emulate UMIP instructions and return dummy values
+ * @insn:	Instruction structure with operands
+ * @umip_inst:	A constant indicating the instruction to emulate
+ * @data:	Buffer into which the dummy result is stored
+ * @data_size:	Size of the emulated result
+ *
+ * Emulate an instruction protected by UMIP and provide a dummy result. The
+ * result of the emulation is saved in @data. The size of the results depends
+ * on both the instruction and type of operand (register vs memory address).
+ * The size of the result is updated in @data_size. Caller is responsible
+ * of providing a @data buffer of at least UMIP_GDT_IDT_BASE_SIZE +
+ * UMIP_GDT_IDT_LIMIT_SIZE bytes.
+ *
+ * Returns:
+ *
+ * 0 on success, -EINVAL on error while emulating.
+ */
+static int emulate_umip_insn(struct insn *insn, int umip_inst,
+			     unsigned char *data, int *data_size)
+{
+	unsigned long dummy_base_addr, dummy_value;
+	unsigned short dummy_limit = 0;
+
+	if (!data || !data_size || !insn)
+		return -EINVAL;
+	/*
+	 * These two instructions return the base address and limit of the
+	 * global and interrupt descriptor table, respectively. According to the
+	 * Intel Software Development manual, the base address can be 24-bit,
+	 * 32-bit or 64-bit. Limit is always 16-bit. If the operand size is
+	 * 16-bit, the returned value of the base address is supposed to be a
+	 * zero-extended 24-byte number. However, it seems that a 32-byte number
+	 * is always returned irrespective of the operand size.
+	 */
+	if (umip_inst == UMIP_INST_SGDT || umip_inst == UMIP_INST_SIDT) {
+		/* SGDT and SIDT do not use registers operands. */
+		if (X86_MODRM_MOD(insn->modrm.value) == 3)
+			return -EINVAL;
+
+		if (umip_inst == UMIP_INST_SGDT)
+			dummy_base_addr = UMIP_DUMMY_GDT_BASE;
+		else
+			dummy_base_addr = UMIP_DUMMY_IDT_BASE;
+
+		*data_size = UMIP_GDT_IDT_LIMIT_SIZE + UMIP_GDT_IDT_BASE_SIZE;
+
+		memcpy(data + 2, &dummy_base_addr, UMIP_GDT_IDT_BASE_SIZE);
+		memcpy(data, &dummy_limit, UMIP_GDT_IDT_LIMIT_SIZE);
+
+	} else if (umip_inst == UMIP_INST_SMSW) {
+		dummy_value = CR0_STATE;
+
+		/*
+		 * Even though the CR0 register has 4 bytes, the number
+		 * of bytes to be copied in the result buffer is determined
+		 * by whether the operand is a register or a memory location.
+		 * If operand is a register, return as many bytes as the operand
+		 * size. If operand is memory, return only the two least
+		 * siginificant bytes of CR0.
+		 */
+		if (X86_MODRM_MOD(insn->modrm.value) == 3)
+			*data_size = insn->opnd_bytes;
+		else
+			*data_size = 2;
+
+		memcpy(data, &dummy_value, *data_size);
+	/* STR and SLDT  are not emulated */
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * fixup_umip_exception() - Fixup a general protection fault caused by UMIP
+ * @regs:	Registers as saved when entering the #GP handler
+ *
+ * The instructions sgdt, sidt, str, smsw, sldt cause a general protection
+ * fault if executed with CPL > 0 (i.e., from user space). If the offending
+ * user-space process is not in long mode, this function fixes the exception
+ * up and provides dummy results for sgdt, sidt and smsw; str and sldt are not
+ * fixed up. Also long mode user-space processes are not fixed up.
+ *
+ * If operands are memory addresses, results are copied to user-space memory as
+ * indicated by the instruction pointed by eIP using the registers indicated in
+ * the instruction operands. If operands are registers, results are copied into
+ * the context that was saved when entering kernel mode.
+ *
+ * Returns:
+ *
+ * True if emulation was successful; false if not.
+ */
+bool fixup_umip_exception(struct pt_regs *regs)
+{
+	int not_copied, nr_copied, reg_offset, dummy_data_size, umip_inst;
+	unsigned long seg_base = 0, *reg_addr;
+	/* 10 bytes is the maximum size of the result of UMIP instructions */
+	unsigned char dummy_data[10] = { 0 };
+	unsigned char buf[MAX_INSN_SIZE];
+	void __user *uaddr;
+	struct insn insn;
+	char seg_defs;
+
+	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
+	 * descriptor table), or virtual-8086 mode. In most of the cases
+	 * seg_base will be zero as in USER_CS.
+	 */
+	if (!user_64bit_mode(regs))
+		seg_base = insn_get_seg_base(regs, INAT_SEG_REG_CS);
+
+	if (seg_base == -1L)
+		return false;
+
+	not_copied = copy_from_user(buf, (void __user *)(seg_base + regs->ip),
+				    sizeof(buf));
+	nr_copied = sizeof(buf) - not_copied;
+
+	/*
+	 * The copy_from_user above could have failed if user code is protected
+	 * by a memory protection key. Give up on emulation in such a case.
+	 * Should we issue a page fault?
+	 */
+	if (!nr_copied)
+		return false;
+
+	insn_init(&insn, buf, nr_copied, user_64bit_mode(regs));
+
+	/*
+	 * Override the default operand and address sizes with what is specified
+	 * in the code segment descriptor. The instruction decoder only sets
+	 * the address size it to either 4 or 8 address bytes and does nothing
+	 * for the operand bytes. This OK for most of the cases, but we could
+	 * have special cases where, for instance, a 16-bit code segment
+	 * descriptor is used.
+	 * If there is an address override prefix, the instruction decoder
+	 * correctly updates these values, even for 16-bit defaults.
+	 */
+	seg_defs = insn_get_code_seg_params(regs);
+	if (seg_defs == -EINVAL)
+		return false;
+
+	insn.addr_bytes = INSN_CODE_SEG_ADDR_SZ(seg_defs);
+	insn.opnd_bytes = INSN_CODE_SEG_OPND_SZ(seg_defs);
+
+	insn_get_length(&insn);
+	if (nr_copied < insn.length)
+		return false;
+
+	umip_inst = identify_insn(&insn);
+	if (umip_inst < 0)
+		return false;
+
+	if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size))
+		return false;
+
+	/*
+	 * If operand is a register, write result to the copy of the register
+	 * value that was pushed to the stack when entering into kernel mode.
+	 * Upon exit, the value we write will be restored to the actual hardware
+	 * register.
+	 */
+	if (X86_MODRM_MOD(insn.modrm.value) == 3) {
+		reg_offset = insn_get_modrm_rm_off(&insn, regs);
+
+		/*
+		 * Negative values are usually errors. In memory addressing,
+		 * the exception is -EDOM. Since we expect a register operand,
+		 * all negative values are errors.
+		 */
+		if (reg_offset < 0)
+			return false;
+
+		reg_addr = (unsigned long *)((unsigned long)regs + reg_offset);
+		memcpy(reg_addr, dummy_data, dummy_data_size);
+	} else {
+		uaddr = insn_get_addr_ref(&insn, regs);
+		if ((unsigned long)uaddr == -1L)
+			return false;
+
+		nr_copied = copy_to_user(uaddr, dummy_data, dummy_data_size);
+		if (nr_copied  > 0)
+			return false;
+	}
+
+	/* increase IP to let the program keep going */
+	regs->ip += insn.length;
+	return true;
+}

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [tip:x86/asm] x86/umip: Force a page fault when unable to copy emulated result to user
  2017-11-06  2:27 ` [PATCH v11 08/12] x86/umip: Force a page fault when unable to copy emulated result to user Ricardo Neri
@ 2017-11-08 11:00   ` tip-bot for Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 11:00 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: akpm, ravi.v.shankar, torvalds, mhiramat, dave.hansen, tony.luck,
	pbonzini, hpa, bp, jslaby, shuah, tglx, paul.gortmaker, slaoub,
	ricardo.neri-calderon, luto, peterz, linux-kernel, fenghua.yu,
	corbet, brgerst, mingo, mst, dvlasenk, jpoimboe, bp, cmetcalf,
	vbabka, ray.huang

Commit-ID:  c6a960bbf6a36572a06bde866d94a7338c7f256a
Gitweb:     https://git.kernel.org/tip/c6a960bbf6a36572a06bde866d94a7338c7f256a
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:53 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:22 +0100

x86/umip: Force a page fault when unable to copy emulated result to user

fixup_umip_exception() will be called from do_general_protection(). If the
former returns false, the latter will issue a SIGSEGV with SEND_SIG_PRIV.
However, when emulation is successful but the emulated result cannot be
copied to user space memory, it is more accurate to issue a SIGSEGV with
SEGV_MAPERR with the offending address. A new function, inspired in
force_sig_info_fault(), is introduced to model the page fault.

Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-9-git-send-email-ricardo.neri-calderon@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/kernel/umip.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index d80b816..6ba82be 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -11,6 +11,10 @@
 #include <asm/traps.h>
 #include <asm/insn.h>
 #include <asm/insn-eval.h>
+#include <linux/ratelimit.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "umip: " fmt
 
 /** DOC: Emulation for User-Mode Instruction Prevention (UMIP)
  *
@@ -196,6 +200,41 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst,
 }
 
 /**
+ * force_sig_info_umip_fault() - Force a SIGSEGV with SEGV_MAPERR
+ * @addr:	Address that caused the signal
+ * @regs:	Register set containing the instruction pointer
+ *
+ * Force a SIGSEGV signal with SEGV_MAPERR as the error code. This function is
+ * intended to be used to provide a segmentation fault when the result of the
+ * UMIP emulation could not be copied to the user space memory.
+ *
+ * Returns: none
+ */
+static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs)
+{
+	siginfo_t info;
+	struct task_struct *tsk = current;
+
+	tsk->thread.cr2		= (unsigned long)addr;
+	tsk->thread.error_code	= X86_PF_USER | X86_PF_WRITE;
+	tsk->thread.trap_nr	= X86_TRAP_PF;
+
+	info.si_signo	= SIGSEGV;
+	info.si_errno	= 0;
+	info.si_code	= SEGV_MAPERR;
+	info.si_addr	= addr;
+	force_sig_info(SIGSEGV, &info, tsk);
+
+	if (!(show_unhandled_signals && unhandled_signal(tsk, SIGSEGV)))
+		return;
+
+	pr_err_ratelimited("%s[%d] umip emulation segfault ip:%lx sp:%lx error:%x in %lx\n",
+			   tsk->comm, task_pid_nr(tsk), regs->ip,
+			   regs->sp, X86_PF_USER | X86_PF_WRITE,
+			   regs->ip);
+}
+
+/**
  * fixup_umip_exception() - Fixup a general protection fault caused by UMIP
  * @regs:	Registers as saved when entering the #GP handler
  *
@@ -311,8 +350,14 @@ bool fixup_umip_exception(struct pt_regs *regs)
 			return false;
 
 		nr_copied = copy_to_user(uaddr, dummy_data, dummy_data_size);
-		if (nr_copied  > 0)
-			return false;
+		if (nr_copied  > 0) {
+			/*
+			 * If copy fails, send a signal and tell caller that
+			 * fault was fixed up.
+			 */
+			force_sig_info_umip_fault(uaddr, regs);
+			return true;
+		}
 	}
 
 	/* increase IP to let the program keep going */

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [tip:x86/asm] x86/umip: Enable User-Mode Instruction Prevention at runtime
  2017-11-06  2:27 ` [PATCH v11 09/12] x86: Enable User-Mode Instruction Prevention at runtime Ricardo Neri
  2017-11-08  9:52   ` Ingo Molnar
@ 2017-11-08 11:01   ` tip-bot for Ricardo Neri
  1 sibling, 0 replies; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 11:01 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: slaoub, torvalds, mst, corbet, shuah, jslaby, luto, fenghua.yu,
	jpoimboe, hpa, cmetcalf, peterz, paul.gortmaker, pbonzini, bp,
	dave.hansen, brgerst, mingo, ravi.v.shankar, tony.luck, akpm,
	ray.huang, dvlasenk, tglx, linux-kernel, vbabka, bp, mhiramat,
	ricardo.neri-calderon

Commit-ID:  aa35f896979d9610bb11df485cf7bb6ca241febb
Gitweb:     https://git.kernel.org/tip/aa35f896979d9610bb11df485cf7bb6ca241febb
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:54 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:23 +0100

x86/umip: Enable User-Mode Instruction Prevention at runtime

User-Mode Instruction Prevention (UMIP) is enabled by setting/clearing a
bit in %cr4.

It makes 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 user space to be protected from. Given these similarities, UMIP can be
enabled along with SMAP and SMEP.

At the moment, UMIP is disabled by default at build time. It can be enabled
at build time by selecting CONFIG_X86_INTEL_UMIP. If enabled at build time,
it can be disabled at run time by adding clearcpuid=514 to the kernel
parameters.

Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-10-git-send-email-ricardo.neri-calderon@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/Kconfig             | 10 ++++++++++
 arch/x86/kernel/cpu/common.c | 25 ++++++++++++++++++++++++-
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 4ae940a..e19fa9f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1802,6 +1802,16 @@ config X86_SMAP
 
 	  If unsure, say Y.
 
+config X86_INTEL_UMIP
+	def_bool n
+	depends on CPU_SUP_INTEL
+	prompt "Intel 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 cdf79ab..47f8a85 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -329,6 +329,28 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c)
 	}
 }
 
+static __always_inline void setup_umip(struct cpuinfo_x86 *c)
+{
+	/* Check the boot processor, plus build option for UMIP. */
+	if (!cpu_feature_enabled(X86_FEATURE_UMIP))
+		goto out;
+
+	/* Check the current processor's cpuid bits. */
+	if (!cpu_has(c, X86_FEATURE_UMIP))
+		goto out;
+
+	cr4_set_bits(X86_CR4_UMIP);
+
+	return;
+
+out:
+	/*
+	 * 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.
  */
@@ -1147,9 +1169,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.

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [tip:x86/asm] x86/traps: Fix up general protection faults caused by UMIP
  2017-11-06  2:27 ` [PATCH v11 10/12] x86/traps: Fixup general protection faults caused by UMIP Ricardo Neri
@ 2017-11-08 11:01   ` tip-bot for Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 11:01 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: cmetcalf, shuah, ravi.v.shankar, hpa, jslaby, pbonzini, luto,
	mingo, tony.luck, ray.huang, peterz, vbabka, paul.gortmaker, mst,
	dvlasenk, mhiramat, corbet, linux-kernel, akpm, torvalds,
	ricardo.neri-calderon, fenghua.yu, dave.hansen, slaoub, tglx,
	brgerst, bp, bp, jpoimboe

Commit-ID:  6fc9dc81bff0ea461db534e2672acfdaf76f3e4e
Gitweb:     https://git.kernel.org/tip/6fc9dc81bff0ea461db534e2672acfdaf76f3e4e
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:55 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:24 +0100

x86/traps: Fix up general protection faults caused by UMIP

If the User-Mode Instruction Prevention CPU feature is available and
enabled, a general protection fault will be issued if the instructions
sgdt, sldt, sidt, str or smsw are executed from user-mode context
(CPL > 0). If the fault was caused by any of the instructions protected
by UMIP, fixup_umip_exception() will emulate dummy results for these
instructions as follows: in virtual-8086 and protected modes, sgdt, sidt
and smsw are emulated; str and sldt are not emulated. No emulation is done
for user-space long mode processes.

If emulation is successful, the emulated result is passed to the user space
program and no SIGSEGV signal is emitted.

Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-11-git-send-email-ricardo.neri-calderon@linux.intel.com
[ Added curly braces. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/kernel/traps.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 42a9c44..ab54bf3 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -60,6 +60,7 @@
 #include <asm/trace/mpx.h>
 #include <asm/mpx.h>
 #include <asm/vm86.h>
+#include <asm/umip.h>
 
 #ifdef CONFIG_X86_64
 #include <asm/x86_init.h>
@@ -513,6 +514,11 @@ do_general_protection(struct pt_regs *regs, long error_code)
 	RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
 	cond_local_irq_enable(regs);
 
+	if (static_cpu_has(X86_FEATURE_UMIP)) {
+		if (user_mode(regs) && fixup_umip_exception(regs))
+			return;
+	}
+
 	if (v8086_mode(regs)) {
 		local_irq_enable();
 		handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [tip:x86/asm] selftests/x86: Add tests for User-Mode Instruction Prevention
  2017-11-06  2:27 ` [PATCH v11 11/12] selftests/x86: Add tests for User-Mode Instruction Prevention Ricardo Neri
@ 2017-11-08 11:02   ` tip-bot for Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 11:02 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ray.huang, dave.hansen, pbonzini, jpoimboe, tglx, corbet,
	torvalds, vbabka, bp, luto, slaoub, akpm, ravi.v.shankar,
	ricardo.neri-calderon, mhiramat, fenghua.yu, tony.luck, cmetcalf,
	paul.gortmaker, brgerst, peterz, mst, linux-kernel, hpa,
	dvlasenk, shuah, jslaby, bp, mingo

Commit-ID:  9390afebe1d3f5a0be18b1afdd0ce09d67cebf9e
Gitweb:     https://git.kernel.org/tip/9390afebe1d3f5a0be18b1afdd0ce09d67cebf9e
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:56 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:24 +0100

selftests/x86: Add tests for User-Mode Instruction Prevention

Certain user space programs that run on virtual-8086 mode may utilize
instructions protected by the User-Mode Instruction Prevention (UMIP)
security feature present in new Intel processors: SGDT, SIDT and SMSW. In
such a case, a general protection fault is issued if UMIP is enabled. When
such a fault happens, the kernel traps it and emulates the results of
these instructions with dummy values. The purpose of this new
test is to verify whether the impacted instructions can be executed
without causing such #GP. If no #GP exceptions occur, we expect to exit
virtual-8086 mode from INT3.

The instructions protected by UMIP are executed in representative use
cases:

 a) displacement-only memory addressing
 b) register-indirect memory addressing
 c) results stored directly in operands

Unfortunately, it is not possible to check the results against a set of
expected values because no emulation will occur in systems that do not
have the UMIP feature. Instead, results are printed for verification. A
simple verification is done to ensure that results of all tests are
identical.

Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-12-git-send-email-ricardo.neri-calderon@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 tools/testing/selftests/x86/entry_from_vm86.c | 73 ++++++++++++++++++++++++++-
 1 file changed, 72 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c
index d075ea0..f7d9cea 100644
--- a/tools/testing/selftests/x86/entry_from_vm86.c
+++ b/tools/testing/selftests/x86/entry_from_vm86.c
@@ -95,6 +95,22 @@ asm (
 	"int3\n\t"
 	"vmcode_int80:\n\t"
 	"int $0x80\n\t"
+	"vmcode_umip:\n\t"
+	/* addressing via displacements */
+	"smsw (2052)\n\t"
+	"sidt (2054)\n\t"
+	"sgdt (2060)\n\t"
+	/* addressing via registers */
+	"mov $2066, %bx\n\t"
+	"smsw (%bx)\n\t"
+	"mov $2068, %bx\n\t"
+	"sidt (%bx)\n\t"
+	"mov $2074, %bx\n\t"
+	"sgdt (%bx)\n\t"
+	/* register operands, only for smsw */
+	"smsw %ax\n\t"
+	"mov %ax, (2080)\n\t"
+	"int3\n\t"
 	".size vmcode, . - vmcode\n\t"
 	"end_vmcode:\n\t"
 	".code32\n\t"
@@ -103,7 +119,7 @@ asm (
 
 extern unsigned char vmcode[], end_vmcode[];
 extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[],
-	vmcode_sti[], vmcode_int3[], vmcode_int80[];
+	vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[];
 
 /* Returns false if the test was skipped. */
 static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
@@ -160,6 +176,58 @@ static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
 	return true;
 }
 
+void do_umip_tests(struct vm86plus_struct *vm86, unsigned char *test_mem)
+{
+	struct table_desc {
+		unsigned short limit;
+		unsigned long base;
+	} __attribute__((packed));
+
+	/* Initialize variables with arbitrary values */
+	struct table_desc gdt1 = { .base = 0x3c3c3c3c, .limit = 0x9999 };
+	struct table_desc gdt2 = { .base = 0x1a1a1a1a, .limit = 0xaeae };
+	struct table_desc idt1 = { .base = 0x7b7b7b7b, .limit = 0xf1f1 };
+	struct table_desc idt2 = { .base = 0x89898989, .limit = 0x1313 };
+	unsigned short msw1 = 0x1414, msw2 = 0x2525, msw3 = 3737;
+
+	/* UMIP -- exit with INT3 unless kernel emulation did not trap #GP */
+	do_test(vm86, vmcode_umip - vmcode, VM86_TRAP, 3, "UMIP tests");
+
+	/* Results from displacement-only addressing */
+	msw1 = *(unsigned short *)(test_mem + 2052);
+	memcpy(&idt1, test_mem + 2054, sizeof(idt1));
+	memcpy(&gdt1, test_mem + 2060, sizeof(gdt1));
+
+	/* Results from register-indirect addressing */
+	msw2 = *(unsigned short *)(test_mem + 2066);
+	memcpy(&idt2, test_mem + 2068, sizeof(idt2));
+	memcpy(&gdt2, test_mem + 2074, sizeof(gdt2));
+
+	/* Results when using register operands */
+	msw3 = *(unsigned short *)(test_mem + 2080);
+
+	printf("[INFO]\tResult from SMSW:[0x%04x]\n", msw1);
+	printf("[INFO]\tResult from SIDT: limit[0x%04x]base[0x%08lx]\n",
+	       idt1.limit, idt1.base);
+	printf("[INFO]\tResult from SGDT: limit[0x%04x]base[0x%08lx]\n",
+	       gdt1.limit, gdt1.base);
+
+	if (msw1 != msw2 || msw1 != msw3)
+		printf("[FAIL]\tAll the results of SMSW should be the same.\n");
+	else
+		printf("[PASS]\tAll the results from SMSW are identical.\n");
+
+	if (memcmp(&gdt1, &gdt2, sizeof(gdt1)))
+		printf("[FAIL]\tAll the results of SGDT should be the same.\n");
+	else
+		printf("[PASS]\tAll the results from SGDT are identical.\n");
+
+	if (memcmp(&idt1, &idt2, sizeof(idt1)))
+		printf("[FAIL]\tAll the results of SIDT should be the same.\n");
+	else
+		printf("[PASS]\tAll the results from SIDT are identical.\n");
+}
+
 int main(void)
 {
 	struct vm86plus_struct v86;
@@ -218,6 +286,9 @@ int main(void)
 	v86.regs.eax = (unsigned int)-1;
 	do_test(&v86, vmcode_int80 - vmcode, VM86_INTx, 0x80, "int80");
 
+	/* UMIP -- should exit with INTx 0x80 unless UMIP was not disabled */
+	do_umip_tests(&v86, addr);
+
 	/* Execute a null pointer */
 	v86.regs.cs = 0;
 	v86.regs.ss = 0;

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [tip:x86/asm] selftests/x86: Add tests for the STR and SLDT instructions
  2017-11-06  2:27 ` [PATCH v11 12/12] selftests/x86: Add tests for instruction str and sldt Ricardo Neri
@ 2017-11-08 11:02   ` tip-bot for Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: tip-bot for Ricardo Neri @ 2017-11-08 11:02 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: torvalds, ray.huang, peterz, mhiramat, shuah, mingo, tglx, bp,
	cmetcalf, fenghua.yu, vbabka, ricardo.neri-calderon, luto,
	jslaby, dave.hansen, corbet, brgerst, hpa, bp, paul.gortmaker,
	mst, ravi.v.shankar, linux-kernel, jpoimboe, dvlasenk, tony.luck,
	slaoub, akpm, pbonzini

Commit-ID:  a9e017d5619eb371460c8e516f4684def62bef3a
Gitweb:     https://git.kernel.org/tip/a9e017d5619eb371460c8e516f4684def62bef3a
Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
AuthorDate: Sun, 5 Nov 2017 18:27:57 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 8 Nov 2017 11:16:25 +0100

selftests/x86: Add tests for the STR and SLDT instructions

The STR and SLDT instructions are not valid when running on virtual-8086
mode and generate an invalid operand exception. These two instructions are
protected by the Intel User-Mode Instruction Prevention (UMIP) security
feature. In protected mode, if UMIP is enabled, these instructions generate
a general protection fault if called from CPL > 0. Linux traps the general
protection fault and emulates the instructions sgdt, sidt and smsw; but not
str and sldt.

These tests are added to verify that the emulation code does not emulate
these two instructions but the expected invalid operand exception is
seen.

Tests fallback to exit with INT3 in case emulation does happen.

Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chen Yucong <slaoub@gmail.com>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: ricardo.neri@intel.com
Link: http://lkml.kernel.org/r/1509935277-22138-13-git-send-email-ricardo.neri-calderon@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 tools/testing/selftests/x86/entry_from_vm86.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c
index f7d9cea..361466a 100644
--- a/tools/testing/selftests/x86/entry_from_vm86.c
+++ b/tools/testing/selftests/x86/entry_from_vm86.c
@@ -111,6 +111,11 @@ asm (
 	"smsw %ax\n\t"
 	"mov %ax, (2080)\n\t"
 	"int3\n\t"
+	"vmcode_umip_str:\n\t"
+	"str %eax\n\t"
+	"vmcode_umip_sldt:\n\t"
+	"sldt %eax\n\t"
+	"int3\n\t"
 	".size vmcode, . - vmcode\n\t"
 	"end_vmcode:\n\t"
 	".code32\n\t"
@@ -119,7 +124,8 @@ asm (
 
 extern unsigned char vmcode[], end_vmcode[];
 extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[],
-	vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[];
+	vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[],
+	vmcode_umip_str[], vmcode_umip_sldt[];
 
 /* Returns false if the test was skipped. */
 static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
@@ -226,6 +232,16 @@ void do_umip_tests(struct vm86plus_struct *vm86, unsigned char *test_mem)
 		printf("[FAIL]\tAll the results of SIDT should be the same.\n");
 	else
 		printf("[PASS]\tAll the results from SIDT are identical.\n");
+
+	sethandler(SIGILL, sighandler, 0);
+	do_test(vm86, vmcode_umip_str - vmcode, VM86_SIGNAL, 0,
+		"STR instruction");
+	clearhandler(SIGILL);
+
+	sethandler(SIGILL, sighandler, 0);
+	do_test(vm86, vmcode_umip_sldt - vmcode, VM86_SIGNAL, 0,
+		"SLDT instruction");
+	clearhandler(SIGILL);
 }
 
 int main(void)

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 11:00   ` [tip:x86/asm] x86/umip: " tip-bot for Ricardo Neri
@ 2017-11-08 16:14     ` Denys Vlasenko
  2017-11-08 16:34       ` Linus Torvalds
  2017-11-09  6:11       ` Ricardo Neri
  0 siblings, 2 replies; 41+ messages in thread
From: Denys Vlasenko @ 2017-11-08 16:14 UTC (permalink / raw)
  To: pbonzini, hpa, bp, vbabka, tony.luck, fenghua.yu, jpoimboe, bp,
	brgerst, corbet, ravi.v.shankar, ricardo.neri-calderon, torvalds,
	cmetcalf, akpm, paul.gortmaker, mhiramat, luto, dave.hansen,
	ray.huang, mst, linux-kernel, peterz, slaoub, mingo, jslaby,
	shuah, tglx, linux-tip-commits

On 11/08/2017 12:00 PM, tip-bot for Ricardo Neri wrote:
> Commit-ID:  1e5db223696afa55e6a038fac638f759e1fdcc01
> Gitweb:     https://git.kernel.org/tip/1e5db223696afa55e6a038fac638f759e1fdcc01
> Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
> AuthorDate: Sun, 5 Nov 2017 18:27:52 -0800
> Committer:  Ingo Molnar <mingo@kernel.org>
> CommitDate: Wed, 8 Nov 2017 11:16:22 +0100
> 
> x86/umip: Add emulation code for UMIP instructions
> 
> The feature User-Mode Instruction Prevention present in recent Intel
> processor prevents a group of instructions (sgdt, sidt, sldt, smsw, and
> str) from being executed with CPL > 0. Otherwise, a general protection
> fault is issued.

This was arguably an oversight on Intel's part - these insns should have been
protected from the start, as they leak a tiny bit of kernel data.

> Rather than relaying to the user space the general protection fault caused
> by the UMIP-protected instructions (in the form of a SIGSEGV signal), it
> can be trapped and the instruction emulated to provide a dummy result.
> This allows to both conserve the current kernel behavior and not reveal the
> system resources that UMIP intends to protect (i.e., the locations of the
> global descriptor and interrupt descriptor tables, the segment selectors of
> the local descriptor table, the value of the task state register and the
> contents of the CR0 register).
> 
> This emulation is needed because certain applications (e.g., WineHQ and
> DOSEMU2) rely on this subset of instructions to function.

I'm surprised. What in the world they need those insns for?

Wine uses sidt like this, to emulate "mov from r/m to reg" insns:

static LDT_ENTRY idt[256];
...
     case 0x8a: /* mov Eb, Gb */
     case 0x8b: /* mov Ev, Gv */
     {
         BYTE *data = INSTR_GetOperandAddr(context, instr + 1, long_addr,
                                           segprefix, &len);
         unsigned int data_size = (*instr == 0x8b) ? (long_op ? 4 : 2) : 1;
         struct idtr idtr = get_idtr(); <=============================== HERE
         unsigned int offset = data - idtr.base;

         if (offset <= idtr.limit + 1 - data_size)
         {
             idt[1].LimitLow = 0x100; /* FIXME */
             idt[2].LimitLow = 0x11E; /* FIXME */
             idt[3].LimitLow = 0x500; /* FIXME */

             switch (*instr)
             {
             case 0x8a: store_reg_byte( context, instr[1], (BYTE *)idt + offset ); break;
             case 0x8b: store_reg_word( context, instr[1], (BYTE *)idt + offset, long_op ); break;
             }
             context->Eip += prefixlen + len + 1;
             return ExceptionContinueExecution;
         }
         break;  /* Unable to emulate it */
     }

Looks baffling, to say the least... this supports someone who reads
IDT bytes via those insns, and they need to ensure that the values read
from idt[1/2/3].LimitLow are as expected. That's it? Pity git history
doesn't go far enough in the past, and comments are not informative as well...

I did not find smsw or sgdt in Wine git tree.

I did not find smsw, sidt or sgdt in dosemu2-devel git tree.

Can we avoid maintain emulation of these isns, by asking Wine to remove their use instead?

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 16:14     ` Denys Vlasenko
@ 2017-11-08 16:34       ` Linus Torvalds
  2017-11-08 16:38         ` H. Peter Anvin
                           ` (2 more replies)
  2017-11-09  6:11       ` Ricardo Neri
  1 sibling, 3 replies; 41+ messages in thread
From: Linus Torvalds @ 2017-11-08 16:34 UTC (permalink / raw)
  To: Denys Vlasenko
  Cc: Paolo Bonzini, Peter Anvin, Borislav Petkov, Vlastimil Babka,
	Tony Luck, Fenghua Yu, Josh Poimboeuf, Borislav Petkov,
	Brian Gerst, Jonathan Corbet, Ravi V. Shankar,
	ricardo.neri-calderon, Chris Metcalf, Andrew Morton,
	Paul Gortmaker, Masami Hiramatsu, Andrew Lutomirski, Dave Hansen,
	ray.huang, Michael S. Tsirkin, Linux Kernel Mailing List,
	Peter Zijlstra, Chen Yucong, Ingo Molnar, Jiri Slaby, Shuah Khan,
	Thomas Gleixner, linux-tip-commits

On Wed, Nov 8, 2017 at 8:14 AM, Denys Vlasenko <dvlasenk@redhat.com> wrote:
>
> Can we avoid maintain emulation of these isns, by asking Wine to remove
> their use instead?

If we ask the Wine people to remove the instruction use, that may mean
that we can avoid the emulation in four or five _years_ once everybody
has updated.

But it wouldn't mean that we could avoid it today.

We *do* probably want to print a warning about these instructions,
whether emulated or not. If emulated, we want to print a warning about
the emulation being expensive (as a nudge to the Wine people to not do
that), and if _not_ emulated, we'd want to print a warning about why
people suddenly got a SIGSEGV in case there are programs that use
those instructions that people didn't even think of.

But make it ratelimit the warning (perhaps at most once every few
minutes or whatever), so that people won't flood message logs just
because they have old stupid programs that use those things.

             Linus

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 16:34       ` Linus Torvalds
@ 2017-11-08 16:38         ` H. Peter Anvin
  2017-11-08 16:53         ` Denys Vlasenko
  2017-11-09  6:13         ` Ricardo Neri
  2 siblings, 0 replies; 41+ messages in thread
From: H. Peter Anvin @ 2017-11-08 16:38 UTC (permalink / raw)
  To: Linus Torvalds, Denys Vlasenko
  Cc: Paolo Bonzini, Borislav Petkov, Vlastimil Babka, Tony Luck,
	Fenghua Yu, Josh Poimboeuf, Borislav Petkov, Brian Gerst,
	Jonathan Corbet, Ravi V. Shankar, ricardo.neri-calderon,
	Chris Metcalf, Andrew Morton, Paul Gortmaker, Masami Hiramatsu,
	Andrew Lutomirski, Dave Hansen, ray.huang, Michael S. Tsirkin,
	Linux Kernel Mailing List, Peter Zijlstra, Chen Yucong,
	Ingo Molnar, Jiri Slaby, Shuah Khan, Thomas Gleixner,
	linux-tip-commits@vger.kernel.org

<linux-tip-commits@vger.kernel.org>
From: hpa@zytor.com
Message-ID: <67A3DB9F-E58D-42B3-BF16-AC59D2FCECC2@zytor.com>

On November 8, 2017 8:34:45 AM PST, Linus Torvalds <torvalds@linux-foundation.org> wrote:
>On Wed, Nov 8, 2017 at 8:14 AM, Denys Vlasenko <dvlasenk@redhat.com>
>wrote:
>>
>> Can we avoid maintain emulation of these isns, by asking Wine to
>remove
>> their use instead?
>
>If we ask the Wine people to remove the instruction use, that may mean
>that we can avoid the emulation in four or five _years_ once everybody
>has updated.
>
>But it wouldn't mean that we could avoid it today.
>
>We *do* probably want to print a warning about these instructions,
>whether emulated or not. If emulated, we want to print a warning about
>the emulation being expensive (as a nudge to the Wine people to not do
>that), and if _not_ emulated, we'd want to print a warning about why
>people suddenly got a SIGSEGV in case there are programs that use
>those instructions that people didn't even think of.
>
>But make it ratelimit the warning (perhaps at most once every few
>minutes or whatever), so that people won't flood message logs just
>because they have old stupid programs that use those things.
>
>             Linus

The real problem is that 16-bit software uses the instructions mostly for stupid reasons, but smsw in particular is used exactly because it is a virtualization hole.
-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 16:34       ` Linus Torvalds
  2017-11-08 16:38         ` H. Peter Anvin
@ 2017-11-08 16:53         ` Denys Vlasenko
  2017-11-08 16:57           ` Linus Torvalds
  2017-11-08 17:24           ` Alan Cox
  2017-11-09  6:13         ` Ricardo Neri
  2 siblings, 2 replies; 41+ messages in thread
From: Denys Vlasenko @ 2017-11-08 16:53 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Paolo Bonzini, Peter Anvin, Borislav Petkov, Vlastimil Babka,
	Tony Luck, Fenghua Yu, Josh Poimboeuf, Borislav Petkov,
	Brian Gerst, Jonathan Corbet, Ravi V. Shankar,
	ricardo.neri-calderon, Chris Metcalf, Andrew Morton,
	Paul Gortmaker, Masami Hiramatsu, Andrew Lutomirski, Dave Hansen,
	ray.huang, Michael S. Tsirkin, Linux Kernel Mailing List,
	Peter Zijlstra, Chen Yucong, Ingo Molnar, Jiri Slaby, Shuah Khan,
	Thomas Gleixner, linux-tip-commits

On 11/08/2017 05:34 PM, Linus Torvalds wrote:
> On Wed, Nov 8, 2017 at 8:14 AM, Denys Vlasenko <dvlasenk@redhat.com> wrote:
>>
>> Can we avoid maintain emulation of these isns, by asking Wine to remove
>> their use instead?
> 
> If we ask the Wine people to remove the instruction use, that may mean
> that we can avoid the emulation in four or five _years_ once everybody
> has updated.
> 
> But it wouldn't mean that we could avoid it today.

We can postpone enabling UMIP by default by a year or so.
By this time, new Wine will be on majority of users' machines.

Then, when kernels switch to enable UMIP by default, umip=0
kernel flag can be used if somebody for some reason updates
their kernel but not Wine.

This is much less code, and simpler code, than implementing SIDT et al
emulation.
Keep in mind that our SIDT emulation itself can turn out to be buggy,
in the worst case it may end up having worse holes that
SIDT isns was - what if it can be tricked into writing into
arbitrary kernel address?

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 16:53         ` Denys Vlasenko
@ 2017-11-08 16:57           ` Linus Torvalds
  2017-11-08 17:09             ` Denys Vlasenko
  2017-11-08 17:24           ` Alan Cox
  1 sibling, 1 reply; 41+ messages in thread
From: Linus Torvalds @ 2017-11-08 16:57 UTC (permalink / raw)
  To: Denys Vlasenko
  Cc: Paolo Bonzini, Peter Anvin, Borislav Petkov, Vlastimil Babka,
	Tony Luck, Fenghua Yu, Josh Poimboeuf, Borislav Petkov,
	Brian Gerst, Jonathan Corbet, Ravi V. Shankar,
	ricardo.neri-calderon, Chris Metcalf, Andrew Morton,
	Paul Gortmaker, Masami Hiramatsu, Andrew Lutomirski, Dave Hansen,
	ray.huang, Michael S. Tsirkin, Linux Kernel Mailing List,
	Peter Zijlstra, Chen Yucong, Ingo Molnar, Jiri Slaby, Shuah Khan,
	Thomas Gleixner, linux-tip-commits

On Wed, Nov 8, 2017 at 8:53 AM, Denys Vlasenko <dvlasenk@redhat.com> wrote:
> We can postpone enabling UMIP by default by a year or so.
> By this time, new Wine will be on majority of users' machines.

So you are suggesting we run unnecessarily insecure, only in order to
not do the emulation that we already have the code for and that the
patch implements?

Why?

Because quite frankly, that sounds f*cking retarded.

          Linus

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 16:57           ` Linus Torvalds
@ 2017-11-08 17:09             ` Denys Vlasenko
  2017-11-08 17:14               ` Paolo Bonzini
  0 siblings, 1 reply; 41+ messages in thread
From: Denys Vlasenko @ 2017-11-08 17:09 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Paolo Bonzini, Peter Anvin, Borislav Petkov, Vlastimil Babka,
	Tony Luck, Fenghua Yu, Josh Poimboeuf, Borislav Petkov,
	Brian Gerst, Jonathan Corbet, Ravi V. Shankar,
	ricardo.neri-calderon, Chris Metcalf, Andrew Morton,
	Paul Gortmaker, Masami Hiramatsu, Andrew Lutomirski, Dave Hansen,
	ray.huang, Michael S. Tsirkin, Linux Kernel Mailing List,
	Peter Zijlstra, Chen Yucong, Ingo Molnar, Jiri Slaby, Shuah Khan,
	Thomas Gleixner, linux-tip-commits

On 11/08/2017 05:57 PM, Linus Torvalds wrote:
> On Wed, Nov 8, 2017 at 8:53 AM, Denys Vlasenko <dvlasenk@redhat.com> wrote:
>> We can postpone enabling UMIP by default by a year or so.
>> By this time, new Wine will be on majority of users' machines.
> 
> So you are suggesting we run unnecessarily insecure, only in order to
> not do the emulation that we already have the code for and that the
> patch implements?

We ran insecure in this way for ~25 years.

> Why?

To avoid having to maintain more obscure, rarely executed code.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 17:09             ` Denys Vlasenko
@ 2017-11-08 17:14               ` Paolo Bonzini
  2017-11-08 17:24                 ` Denys Vlasenko
  2017-11-09  6:17                 ` Ricardo Neri
  0 siblings, 2 replies; 41+ messages in thread
From: Paolo Bonzini @ 2017-11-08 17:14 UTC (permalink / raw)
  To: Denys Vlasenko, Linus Torvalds
  Cc: Peter Anvin, Borislav Petkov, Vlastimil Babka, Tony Luck,
	Fenghua Yu, Josh Poimboeuf, Borislav Petkov, Brian Gerst,
	Jonathan Corbet, Ravi V. Shankar, ricardo.neri-calderon,
	Chris Metcalf, Andrew Morton, Paul Gortmaker, Masami Hiramatsu,
	Andrew Lutomirski, Dave Hansen, ray.huang, Michael S. Tsirkin,
	Linux Kernel Mailing List, Peter Zijlstra, Chen Yucong,
	Ingo Molnar, Jiri Slaby, Shuah Khan, Thomas Gleixner,
	linux-tip-commits

On 08/11/2017 18:09, Denys Vlasenko wrote:
> On 11/08/2017 05:57 PM, Linus Torvalds wrote:
>> On Wed, Nov 8, 2017 at 8:53 AM, Denys Vlasenko <dvlasenk@redhat.com>
>> wrote:
>>> We can postpone enabling UMIP by default by a year or so.
>>> By this time, new Wine will be on majority of users' machines.
>>
>> So you are suggesting we run unnecessarily insecure, only in order to
>> not do the emulation that we already have the code for and that the
>> patch implements?
> 
> We ran insecure in this way for ~25 years.
> 
>> Why?
> 
> To avoid having to maintain more obscure, rarely executed code.

As a start, you could propose a patch to disable the emulation code
through a sysctl or Kconfig symbol.  I would be surprised if it takes
more time than what you've spent writing emails in this thread.

Paolo

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 16:53         ` Denys Vlasenko
  2017-11-08 16:57           ` Linus Torvalds
@ 2017-11-08 17:24           ` Alan Cox
  1 sibling, 0 replies; 41+ messages in thread
From: Alan Cox @ 2017-11-08 17:24 UTC (permalink / raw)
  To: Denys Vlasenko
  Cc: Linus Torvalds, Paolo Bonzini, Peter Anvin, Borislav Petkov,
	Vlastimil Babka, Tony Luck, Fenghua Yu, Josh Poimboeuf,
	Borislav Petkov, Brian Gerst, Jonathan Corbet, Ravi V. Shankar,
	ricardo.neri-calderon, Chris Metcalf, Andrew Morton,
	Paul Gortmaker, Masami Hiramatsu, Andrew Lutomirski, Dave Hansen,
	ray.huang, Michael S. Tsirkin, Linux Kernel Mailing List,
	Peter Zijlstra, Chen Yucong, Ingo Molnar, Jiri Slaby, Shuah Khan,
	Thomas Gleixner,
	linux-tip-commits@vger.kernel.org"
	<linux-tip-commits@vger.kernel.org>

On Wed, 8 Nov 2017 17:53:12 +0100
Denys Vlasenko <dvlasenk@redhat.com> wrote:

> On 11/08/2017 05:34 PM, Linus Torvalds wrote:
> > On Wed, Nov 8, 2017 at 8:14 AM, Denys Vlasenko <dvlasenk@redhat.com> wrote:  
> >>
> >> Can we avoid maintain emulation of these isns, by asking Wine to remove
> >> their use instead?  
> > 
> > If we ask the Wine people to remove the instruction use, that may mean
> > that we can avoid the emulation in four or five _years_ once everybody
> > has updated.
> > 
> > But it wouldn't mean that we could avoid it today.  
> 
> We can postpone enabling UMIP by default by a year or so.
> By this time, new Wine will be on majority of users' machines.

And because Wine compatibility is a bit random at times many users will
have multiple wine versiosn at once on their system which they expect to
continue to work as they used to. For gaming in particularl that isn't
going to change. There are even front ends that let you package up games
with the right matching wine they were tested with.

Alan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 17:14               ` Paolo Bonzini
@ 2017-11-08 17:24                 ` Denys Vlasenko
  2017-11-09  6:17                 ` Ricardo Neri
  1 sibling, 0 replies; 41+ messages in thread
From: Denys Vlasenko @ 2017-11-08 17:24 UTC (permalink / raw)
  To: Paolo Bonzini, Linus Torvalds
  Cc: Peter Anvin, Borislav Petkov, Vlastimil Babka, Tony Luck,
	Fenghua Yu, Josh Poimboeuf, Borislav Petkov, Brian Gerst,
	Jonathan Corbet, Ravi V. Shankar, ricardo.neri-calderon,
	Chris Metcalf, Andrew Morton, Paul Gortmaker, Masami Hiramatsu,
	Andrew Lutomirski, Dave Hansen, ray.huang, Michael S. Tsirkin,
	Linux Kernel Mailing List, Peter Zijlstra, Chen Yucong,
	Ingo Molnar, Jiri Slaby, Shuah Khan, Thomas Gleixner,
	linux-tip-commits

On 11/08/2017 06:14 PM, Paolo Bonzini wrote:
> On 08/11/2017 18:09, Denys Vlasenko wrote:
>> On 11/08/2017 05:57 PM, Linus Torvalds wrote:
>>> On Wed, Nov 8, 2017 at 8:53 AM, Denys Vlasenko <dvlasenk@redhat.com>
>>> wrote:
>>>> We can postpone enabling UMIP by default by a year or so.
>>>> By this time, new Wine will be on majority of users' machines.
>>>
>>> So you are suggesting we run unnecessarily insecure, only in order to
>>> not do the emulation that we already have the code for and that the
>>> patch implements?
>>
>> We ran insecure in this way for ~25 years.
>>
>>> Why?
>>
>> To avoid having to maintain more obscure, rarely executed code.
> 
> As a start, you could propose a patch to disable the emulation code
> through a sysctl or Kconfig symbol.

This way, the emulation code will still be in the kernel, and still
need to be maintained.

In my opinion, if we do emulate these insns, then adding even more code
to disable that emulation is not worth doing.

> I would be surprised if it takes
> more time than what you've spent writing emails in this thread.

Yes, I not only f**ing retarded, I'm also lazy. Thanks guys...

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention
  2017-11-08 10:00 ` [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Thomas Gleixner
@ 2017-11-09  5:46   ` Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: Ricardo Neri @ 2017-11-09  5:46 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Ingo Molnar, H. Peter Anvin, Andy Lutomirski, Borislav Petkov,
	Peter Zijlstra, Andrew Morton, Brian Gerst, Chris Metcalf,
	Dave Hansen, Paolo Bonzini, Masami Hiramatsu, Huang Rui,
	Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin, Paul Gortmaker,
	Vlastimil Babka, Chen Yucong, Ravi V. Shankar, Shuah Khan,
	linux-kernel, x86, ricardo.neri, Tony Luck

On Wed, Nov 08, 2017 at 11:00:13AM +0100, Thomas Gleixner wrote:
> On Sun, 5 Nov 2017, Ricardo Neri wrote:
> > Changes since V10:
> > *Patch 1 ("x86/insn-eval: Extend get_seg_base_addr() to also obtain segment
> >  limit") of v10 has been dropped has it has been merged in the tip tree.
> > *Removed unnecessary wrap-around of function calls to enforce the 80
> >  chars-per-line rule. In some cases, variables were renamed.
> > *Removed unnecessary casts between variables of the same width.
> > *Reworked casts between variables of different width in favor of bit
> >  masks. Casts were kept for arithmetic operations.
> > *Reworded patch descriptions and documentation of several functions to
> >  improve clarity.
> 
> For the whole series:
> 
> Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

Thank you Thomas!

BR,
Ricardo

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v11 09/12] x86: Enable User-Mode Instruction Prevention at runtime
  2017-11-08  9:52   ` Ingo Molnar
@ 2017-11-09  5:51     ` Ricardo Neri
  0 siblings, 0 replies; 41+ messages in thread
From: Ricardo Neri @ 2017-11-09  5:51 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andy Lutomirski,
	Borislav Petkov, Peter Zijlstra, Andrew Morton, Brian Gerst,
	Chris Metcalf, Dave Hansen, Paolo Bonzini, Masami Hiramatsu,
	Huang Rui, Jiri Slaby, Jonathan Corbet, Michael S. Tsirkin,
	Paul Gortmaker, Vlastimil Babka, Chen Yucong, Ravi V. Shankar,
	Shuah Khan, linux-kernel, x86, ricardo.neri, Tony Luck,
	Fenghua Yu

On Wed, Nov 08, 2017 at 10:52:59AM +0100, Ingo Molnar wrote:
> 
> * Ricardo Neri <ricardo.neri-calderon@linux.intel.com> wrote:
> 
> > User-Mode Instruction Prevention (UMIP) is enabled by setting/clearing a
> > bit in %cr4.
> > 
> > It makes 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 user space to be protected from. Given these similarities, UMIP can be
> > enabled along with SMAP and SMEP.
> > 
> > At the moment, UMIP is disabled by default at build time. It can be enabled
> > at build time by selecting CONFIG_X86_INTEL_UMIP. If enabled at build time,
> > it can be disabled at run time by adding clearcpuid=514 to the kernel
> > parameters.
> 
> > +config X86_INTEL_UMIP
> > +	def_bool n
> > +	depends on CPU_SUP_INTEL
> > +	prompt "Intel 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.
> 
> Ok, I really like this latest series.

Thanks!

> 
> One small request: could you please make the feature default-y, which is what we 
> do for new hardware features that don't have a significant runtime cost. There's 
> no ABI breakage expected, right?

No, no ABI breakage should happen. The only visible change is that processes running
in user long mode will see a SIGSEGV signal if they try to use any of the instructions
that UMIP protects. Also, any process using SLDT or or STR will see the SIGSEGV signal.

I will submit an extra patch to do this default-y.
> 
> Another request: could you please extend the Kconfig description to _explain_ to 
> the user why this feature is useful - in a short sentence or so. I.e. point out 
> that these instructions expose information about hardware state that is not really 
> necessary for the vast majority of applications.

Sure, I will submit an extra with this explanation.
> 
> Plus:
> 
> > +       cr4_set_bits(X86_CR4_UMIP);
> 
> Please also inform admins that it's enabled, via something like:
> 
> 	pr_info("x86/cpu: Activated the Intel User Mode Instruction Prevention (UMIP) CPU feature\n");

Will do.
> 
> ... or so.
> 
> Please do these changes in a separate add-on patch #13 on top of this series, as 
> I've already started testing these bits.

Sure.

Thanks and BR,
Ricardo

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 16:14     ` Denys Vlasenko
  2017-11-08 16:34       ` Linus Torvalds
@ 2017-11-09  6:11       ` Ricardo Neri
  1 sibling, 0 replies; 41+ messages in thread
From: Ricardo Neri @ 2017-11-09  6:11 UTC (permalink / raw)
  To: Denys Vlasenko
  Cc: pbonzini, hpa, bp, vbabka, tony.luck, fenghua.yu, jpoimboe, bp,
	brgerst, corbet, ravi.v.shankar, torvalds, cmetcalf, akpm,
	paul.gortmaker, mhiramat, luto, dave.hansen, ray.huang, mst,
	linux-kernel, peterz, slaoub, mingo, jslaby, shuah, tglx,
	linux-tip-commits

On Wed, Nov 08, 2017 at 05:14:33PM +0100, Denys Vlasenko wrote:
> On 11/08/2017 12:00 PM, tip-bot for Ricardo Neri wrote:
> >Commit-ID:  1e5db223696afa55e6a038fac638f759e1fdcc01
> >Gitweb:     https://git.kernel.org/tip/1e5db223696afa55e6a038fac638f759e1fdcc01
> >Author:     Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
> >AuthorDate: Sun, 5 Nov 2017 18:27:52 -0800
> >Committer:  Ingo Molnar <mingo@kernel.org>
> >CommitDate: Wed, 8 Nov 2017 11:16:22 +0100
> >
> >x86/umip: Add emulation code for UMIP instructions
> >
> >The feature User-Mode Instruction Prevention present in recent Intel
> >processor prevents a group of instructions (sgdt, sidt, sldt, smsw, and
> >str) from being executed with CPL > 0. Otherwise, a general protection
> >fault is issued.
> 
> This was arguably an oversight on Intel's part - these insns should have been
> protected from the start, as they leak a tiny bit of kernel data.
> 
> >Rather than relaying to the user space the general protection fault caused
> >by the UMIP-protected instructions (in the form of a SIGSEGV signal), it
> >can be trapped and the instruction emulated to provide a dummy result.
> >This allows to both conserve the current kernel behavior and not reveal the
> >system resources that UMIP intends to protect (i.e., the locations of the
> >global descriptor and interrupt descriptor tables, the segment selectors of
> >the local descriptor table, the value of the task state register and the
> >contents of the CR0 register).
> >
> >This emulation is needed because certain applications (e.g., WineHQ and
> >DOSEMU2) rely on this subset of instructions to function.
> 
> I'm surprised. What in the world they need those insns for?
> 
> Wine uses sidt like this, to emulate "mov from r/m to reg" insns:
> 
> static LDT_ENTRY idt[256];
> ...
>     case 0x8a: /* mov Eb, Gb */
>     case 0x8b: /* mov Ev, Gv */
>     {
>         BYTE *data = INSTR_GetOperandAddr(context, instr + 1, long_addr,
>                                           segprefix, &len);
>         unsigned int data_size = (*instr == 0x8b) ? (long_op ? 4 : 2) : 1;
>         struct idtr idtr = get_idtr(); <=============================== HERE
>         unsigned int offset = data - idtr.base;
> 
>         if (offset <= idtr.limit + 1 - data_size)
>         {
>             idt[1].LimitLow = 0x100; /* FIXME */
>             idt[2].LimitLow = 0x11E; /* FIXME */
>             idt[3].LimitLow = 0x500; /* FIXME */
> 
>             switch (*instr)
>             {
>             case 0x8a: store_reg_byte( context, instr[1], (BYTE *)idt + offset ); break;
>             case 0x8b: store_reg_word( context, instr[1], (BYTE *)idt + offset, long_op ); break;
>             }
>             context->Eip += prefixlen + len + 1;
>             return ExceptionContinueExecution;
>         }
>         break;  /* Unable to emulate it */
>     }
> 
> Looks baffling, to say the least... this supports someone who reads
> IDT bytes via those insns, and they need to ensure that the values read
> from idt[1/2/3].LimitLow are as expected. That's it? Pity git history
> doesn't go far enough in the past, and comments are not informative as well...
> 
> I did not find smsw or sgdt in Wine git tree.
> 
> I did not find smsw, sidt or sgdt in dosemu2-devel git tree.

Stas Sergeev investigated what applications use smsw when running dosemu2 in virtual-8086
mode. He found that Windows 3.1 and dos4gw use it [1], [2].

Thanks and BR,
Ricardo

[1]. https://www.winehq.org/pipermail/wine-devel/2017-April/117159.html
[2]. https://marc.info/?l=linux-kernel&m=147876798717927&w=2

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 16:34       ` Linus Torvalds
  2017-11-08 16:38         ` H. Peter Anvin
  2017-11-08 16:53         ` Denys Vlasenko
@ 2017-11-09  6:13         ` Ricardo Neri
  2 siblings, 0 replies; 41+ messages in thread
From: Ricardo Neri @ 2017-11-09  6:13 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Denys Vlasenko, Paolo Bonzini, Peter Anvin, Borislav Petkov,
	Vlastimil Babka, Tony Luck, Fenghua Yu, Josh Poimboeuf,
	Borislav Petkov, Brian Gerst, Jonathan Corbet, Ravi V. Shankar,
	Chris Metcalf, Andrew Morton, Paul Gortmaker, Masami Hiramatsu,
	Andrew Lutomirski, Dave Hansen, ray.huang, Michael S. Tsirkin,
	Linux Kernel Mailing List, Peter Zijlstra, Chen Yucong,
	Ingo Molnar, Jiri Slaby, Shuah Khan, Thomas Gleixner,
	linux-tip-commits

On Wed, Nov 08, 2017 at 08:34:45AM -0800, Linus Torvalds wrote:
> On Wed, Nov 8, 2017 at 8:14 AM, Denys Vlasenko <dvlasenk@redhat.com> wrote:
> >
> > Can we avoid maintain emulation of these isns, by asking Wine to remove
> > their use instead?
> 
> If we ask the Wine people to remove the instruction use, that may mean
> that we can avoid the emulation in four or five _years_ once everybody
> has updated.
> 
> But it wouldn't mean that we could avoid it today.
> 
> We *do* probably want to print a warning about these instructions,
> whether emulated or not. If emulated, we want to print a warning about
> the emulation being expensive (as a nudge to the Wine people to not do
> that), and if _not_ emulated, we'd want to print a warning about why
> people suddenly got a SIGSEGV in case there are programs that use
> those instructions that people didn't even think of.

I am preparing a set of complementary patches now that the series made it
to the tip tree. I can include these updates as well.
> 
> But make it ratelimit the warning (perhaps at most once every few
> minutes or whatever), so that people won't flood message logs just
> because they have old stupid programs that use those things.

Will do.

Thanks and BR,
Ricardo

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [tip:x86/asm] x86/umip: Add emulation code for UMIP instructions
  2017-11-08 17:14               ` Paolo Bonzini
  2017-11-08 17:24                 ` Denys Vlasenko
@ 2017-11-09  6:17                 ` Ricardo Neri
  1 sibling, 0 replies; 41+ messages in thread
From: Ricardo Neri @ 2017-11-09  6:17 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Denys Vlasenko, Linus Torvalds, Peter Anvin, Borislav Petkov,
	Vlastimil Babka, Tony Luck, Fenghua Yu, Josh Poimboeuf,
	Borislav Petkov, Brian Gerst, Jonathan Corbet, Ravi V. Shankar,
	Chris Metcalf, Andrew Morton, Paul Gortmaker, Masami Hiramatsu,
	Andrew Lutomirski, Dave Hansen, ray.huang, Michael S. Tsirkin,
	Linux Kernel Mailing List, Peter Zijlstra, Chen Yucong,
	Ingo Molnar, Jiri Slaby, Shuah Khan, Thomas Gleixner,
	linux-tip-commits

On Wed, Nov 08, 2017 at 06:14:12PM +0100, Paolo Bonzini wrote:
> On 08/11/2017 18:09, Denys Vlasenko wrote:
> > On 11/08/2017 05:57 PM, Linus Torvalds wrote:
> >> On Wed, Nov 8, 2017 at 8:53 AM, Denys Vlasenko <dvlasenk@redhat.com>
> >> wrote:
> >>> We can postpone enabling UMIP by default by a year or so.
> >>> By this time, new Wine will be on majority of users' machines.
> >>
> >> So you are suggesting we run unnecessarily insecure, only in order to
> >> not do the emulation that we already have the code for and that the
> >> patch implements?
> > 
> > We ran insecure in this way for ~25 years.
> > 
> >> Why?
> > 
> > To avoid having to maintain more obscure, rarely executed code.
> 
> As a start, you could propose a patch to disable the emulation code
> through a sysctl or Kconfig symbol.  I would be surprised if it takes
> more time than what you've spent writing emails in this thread.

Indeed, Andy Lutomirski suggested something similar in the past, but as a
separate series [1].

Plus, the Wine team was also interested in receiving the SIGSEGV that UMIP
would generate, but also acknowledged that it would break existing
versions[2].

Thanks and BR,
Ricardo

[1]. https://lkml.org/lkml/2017/3/8/735
[2]. https://www.winehq.org/pipermail/wine-devel/2016-November/115321.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2017-11-09  6:19 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-06  2:27 [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 01/12] x86/insn-eval: Compute linear address in several utility functions Ricardo Neri
2017-11-08 10:57   ` [tip:x86/asm] " tip-bot for Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 02/12] x86/insn-eval: Add support to resolve 32-bit address encodings Ricardo Neri
2017-11-08 10:58   ` [tip:x86/asm] " tip-bot for Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 03/12] x86/insn-eval: Add wrapper function for 32 and 64-bit addresses Ricardo Neri
2017-11-08 10:58   ` [tip:x86/asm] " tip-bot for Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 04/12] x86/insn-eval: Handle 32-bit address encodings in virtual-8086 mode Ricardo Neri
2017-11-08 10:59   ` [tip:x86/asm] " tip-bot for Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 05/12] x86/insn-eval: Add support to resolve 16-bit address encodings Ricardo Neri
2017-11-08 10:59   ` [tip:x86/asm] " tip-bot for Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 06/12] x86/cpufeature: Add User-Mode Instruction Prevention definitions Ricardo Neri
2017-11-08 10:59   ` [tip:x86/asm] " tip-bot for Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 07/12] x86: Add emulation code for UMIP instructions Ricardo Neri
2017-11-08 11:00   ` [tip:x86/asm] x86/umip: " tip-bot for Ricardo Neri
2017-11-08 16:14     ` Denys Vlasenko
2017-11-08 16:34       ` Linus Torvalds
2017-11-08 16:38         ` H. Peter Anvin
2017-11-08 16:53         ` Denys Vlasenko
2017-11-08 16:57           ` Linus Torvalds
2017-11-08 17:09             ` Denys Vlasenko
2017-11-08 17:14               ` Paolo Bonzini
2017-11-08 17:24                 ` Denys Vlasenko
2017-11-09  6:17                 ` Ricardo Neri
2017-11-08 17:24           ` Alan Cox
2017-11-09  6:13         ` Ricardo Neri
2017-11-09  6:11       ` Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 08/12] x86/umip: Force a page fault when unable to copy emulated result to user Ricardo Neri
2017-11-08 11:00   ` [tip:x86/asm] " tip-bot for Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 09/12] x86: Enable User-Mode Instruction Prevention at runtime Ricardo Neri
2017-11-08  9:52   ` Ingo Molnar
2017-11-09  5:51     ` Ricardo Neri
2017-11-08 11:01   ` [tip:x86/asm] x86/umip: " tip-bot for Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 10/12] x86/traps: Fixup general protection faults caused by UMIP Ricardo Neri
2017-11-08 11:01   ` [tip:x86/asm] x86/traps: Fix up " tip-bot for Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 11/12] selftests/x86: Add tests for User-Mode Instruction Prevention Ricardo Neri
2017-11-08 11:02   ` [tip:x86/asm] " tip-bot for Ricardo Neri
2017-11-06  2:27 ` [PATCH v11 12/12] selftests/x86: Add tests for instruction str and sldt Ricardo Neri
2017-11-08 11:02   ` [tip:x86/asm] selftests/x86: Add tests for the STR and SLDT instructions tip-bot for Ricardo Neri
2017-11-08 10:00 ` [PATCH v11 00/12] x86: Enable User-Mode Instruction Prevention Thomas Gleixner
2017-11-09  5:46   ` Ricardo Neri

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.