public inbox for linux-msdos@vger.kernel.org
 help / color / mirror / Atom feed
From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
To: Ingo Molnar <mingo@redhat.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Andy Lutomirski <luto@kernel.org>, Borislav Petkov <bp@suse.de>
Cc: Peter Zijlstra <peterz@infradead.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Brian Gerst <brgerst@gmail.com>,
	Chris Metcalf <cmetcalf@mellanox.com>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Liang Z Li <liang.z.li@intel.com>,
	Masami Hiramatsu <mhiramat@kernel.org>,
	Huang Rui <ray.huang@amd.com>, Jiri Slaby <jslaby@suse.cz>,
	Jonathan Corbet <corbet@lwn.net>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	Paul Gortmaker <paul.gortmaker@windriver.com>,
	Vlastimil Babka <vbabka@suse.cz>, Chen Yucong <slaoub@gmail.com>,
	Alexandre Julliard <julliard@winehq.org>,
	Stas Sergeev <stsp@list.ru>, Fenghua Yu <fenghua.yu@intel.com>,
	"Ravi V. Shankar" <ravi.v.shankar@intel.com>,
	Shuah Khan <shuah@kernel.org>,
	linux-kernel@vger.kern
Subject: [PATCH v4 05/17] x86/insn-eval: Add utility function to get segment selector
Date: Wed, 22 Feb 2017 22:36:54 -0800	[thread overview]
Message-ID: <20170223063706.71554-6-ricardo.neri-calderon@linux.intel.com> (raw)
In-Reply-To: <20170223063706.71554-1-ricardo.neri-calderon@linux.intel.com>

When computing a linear address and segmentation is used, we need to know
the base address of the segment involved in the computation. In most of
the cases, it will be sufficient to use USER_DS, which has a base of 0.
However, it may be possible that a user space program defines its own
segments via a local descriptor table. Thus, the base address of the
segment is needed.

The segment selector to be used when computing a linear address is
determined by any either segment select override prefixes in the
instruction or the registers involved in the computation of the effective
address; in that order. Also, there are cases when the overrides shall be
ignored.

This function can be used in both protected mode and virtual-8086 mode.
When in protected mode, the segment selector is obtained from the pt_regs
structure. When in virtual-8086 mode, data segments are obtained from the
kernel_vm86_regs.

When in CONFIG_X86_64, selectors for data segments are absent from pt_regs.
Hence, the returned selector is zero to signal that segmentation is not
in use.

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: 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 | 163 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 163 insertions(+)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index 6c62fbf..516902e 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -8,6 +8,7 @@
 #include <asm/inat.h>
 #include <asm/insn.h>
 #include <asm/insn-eval.h>
+#include <asm/vm86.h>
 
 enum reg_type {
 	REG_TYPE_RM = 0,
@@ -15,6 +16,168 @@ enum reg_type {
 	REG_TYPE_BASE,
 };
 
+/**
+ * get_segment_selector() - obtain segment selector
+ * @regs:	Set of registers containing the segment selector
+ * @insn:	Instruction structure with selector override prefixes
+ * @regoff:	Operand offset, in pt_regs, of which the selector is needed
+ *
+ * The segment selector to which an effective address refers depends on
+ * a) segment selector overrides instruction prefixes or b) the operand
+ * register indicated in the ModRM or SiB byte.
+ *
+ * For case a), the function inspects any prefixes in the insn instruction;
+ * insn can be null to indicate that selector override prefixes shall be
+ * ignored. This is useful when the use of prefixes is forbidden (e.g.,
+ * obtaining the code selector). For case b), the operand register shall be
+ * represented as the offset from the base address of pt_regs. Also, regoff
+ * can be -EINVAL for cases in which registers are not used as operands (e.g.,
+ * when the mod and r/m parts of the ModRM byte are 0 and 5, respectively).
+ *
+ * The returned segment selector is obtained from the regs structure. Both
+ * protected and virtual-8086 modes are supported. In virtual-8086 mode,
+ * data segments are obtained from the kernel_vm86_regs structure.
+ * For CONFIG_X86_64, the returned segment selector is null if such selector
+ * refers to es, fs or gs.
+ *
+ * Return: Value of the segment selector
+ */
+static unsigned short get_segment_selector(struct pt_regs *regs,
+					   struct insn *insn, int regoff)
+{
+	int i;
+
+	struct kernel_vm86_regs *vm86regs = (struct kernel_vm86_regs *)regs;
+
+	if (!insn)
+		goto default_seg;
+
+	insn_get_prefixes(insn);
+
+	if (v8086_mode(regs)) {
+		/*
+		 * Check first if we have selector overrides. Having more than
+		 * one selector override leads to undefined behavior. We
+		 * only use the first one and return
+		 */
+		for (i = 0; i < insn->prefixes.nbytes; i++) {
+			switch (insn->prefixes.bytes[i]) {
+			/*
+			 * Code and stack segment selector register are saved in
+			 * all processor modes. Thus, it makes sense to take
+			 * them from pt_regs.
+			 */
+			case 0x2e:
+				return (unsigned short)regs->cs;
+			case 0x36:
+				return (unsigned short)regs->ss;
+			/*
+			 * The rest of the segment selector registers are only
+			 * saved in virtual-8086 mode. Thus, we must obtain them
+			 * from the vm86 register structure.
+			 */
+			case 0x3e:
+				return vm86regs->ds;
+			case 0x26:
+				return vm86regs->es;
+			case 0x64:
+				return vm86regs->fs;
+			case 0x65:
+				return vm86regs->gs;
+			/*
+			 * No default action needed. We simply did not find any
+			 * relevant prefixes.
+			 */
+			}
+		}
+	} else {/* protected mode */
+		/*
+		 * Check first if we have selector overrides. Having more than
+		 * one selector override leads to undefined behavior. We
+		 * only use the first one and return.
+		 */
+		for (i = 0; i < insn->prefixes.nbytes; i++) {
+			switch (insn->prefixes.bytes[i]) {
+			/*
+			 * Code and stack segment selector register are saved in
+			 * all processor modes. Thus, it makes sense to take
+			 * them from pt_regs.
+			 */
+			case 0x2e:
+				return (unsigned short)regs->cs;
+			case 0x36:
+				return (unsigned short)regs->ss;
+#ifdef CONFIG_X86_32
+			case 0x3e:
+				return (unsigned short)regs->ds;
+			case 0x26:
+				return (unsigned short)regs->es;
+			case 0x64:
+				return (unsigned short)regs->fs;
+			case 0x65:
+				return (unsigned short)regs->gs;
+#else
+			/* do not return any segment selector in x86_64 */
+			case 0x3e:
+			case 0x26:
+			case 0x64:
+			case 0x65:
+				return 0;
+#endif
+			/*
+			 * No default action needed. We simply did not find any
+			 * relevant prefixes.
+			 */
+			}
+		}
+	}
+
+default_seg:
+	/*
+	 * If no overrides, use default selectors as described in the
+	 * Intel documentation: SS for ESP or EBP. DS for all data references,
+	 * except when relative to stack or string destination.
+	 * Also, AX, CX and DX are not valid register operands in 16-bit
+	 * address encodings.
+	 * Callers must interpret the result correctly according to the type
+	 * of instructions (e.g., use ES for string instructions).
+	 * Also, some values of modrm and sib might seem to indicate the use
+	 * of EBP and ESP (e.g., modrm_mod = 0, modrm_rm = 5) but actually
+	 * they refer to cases in which only a displacement used. These cases
+	 * should be indentified by the caller and not with this function.
+	 */
+	switch (regoff) {
+	case offsetof(struct pt_regs, ax):
+		/* fall through */
+	case offsetof(struct pt_regs, cx):
+		/* fall through */
+	case offsetof(struct pt_regs, dx):
+		if (insn && insn->addr_bytes == 2)
+			return 0;
+	case -EDOM: /* no register involved in address computation */
+	case offsetof(struct pt_regs, bx):
+		/* fall through */
+	case offsetof(struct pt_regs, di):
+		/* fall through */
+	case offsetof(struct pt_regs, si):
+		if (v8086_mode(regs))
+			return vm86regs->ds;
+#ifdef CONFIG_X86_32
+		return (unsigned short)regs->ds;
+#else
+		return 0;
+#endif
+	case offsetof(struct pt_regs, bp):
+		/* fall through */
+	case offsetof(struct pt_regs, sp):
+		return (unsigned short)regs->ss;
+	case offsetof(struct pt_regs, ip):
+		return (unsigned short)regs->cs;
+	default:
+		return 0;
+	}
+}
+
 static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
 			  enum reg_type type)
 {
-- 
2.9.3


  parent reply	other threads:[~2017-02-23  6:36 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-23  6:36 [PATCH v4 00/17] x86: Enable User-Mode Instruction Prevention Ricardo Neri
2017-02-23  6:36 ` [PATCH v4 01/17] x86/mpx: Do not use SIB index if index points to R/ESP Ricardo Neri
2017-02-23  7:24   ` Peter Zijlstra
2017-02-23  9:50     ` Paul Crawford
2017-02-23 12:47       ` Coding style vs legibility [was Re: [PATCH v4 01/17] x86/mpx: Do not use SIB index if index points to R/ESP] Mouse
2017-02-23 22:17     ` [PATCH v4 01/17] x86/mpx: Do not use SIB index if index points to R/ESP Ricardo Neri
2017-02-24  2:33       ` Joe Perches
2017-02-24  2:41         ` Ricardo Neri
2017-02-24 14:47         ` Nathan Howard
2017-02-24 19:07           ` Ricardo Neri
2017-02-24 15:00         ` Adan Hawthorn
2017-02-23  6:36 ` [PATCH v4 02/17] x86/mpx: Do not use R/EBP as base in the SIB byte with Mod = 0 Ricardo Neri
2017-02-23  6:36 ` [PATCH v4 03/17] x86/mpx, x86/insn: Relocate insn util functions to a new insn-kernel Ricardo Neri
2017-02-23 10:54   ` kbuild test robot
2017-02-23 22:18     ` Ricardo Neri
2017-02-23  6:36 ` [PATCH v4 04/17] x86/insn-eval: Add utility functions to get register offsets Ricardo Neri
2017-02-23  6:36 ` Ricardo Neri [this message]
2017-02-23  6:36 ` [PATCH v4 06/17] x86/insn-eval: Add utility function to get segment descriptor Ricardo Neri
2017-02-23  6:36 ` [PATCH v4 07/17] x86/insn-eval: Add utility function to get segment descriptor base address Ricardo Neri
2017-02-23  6:36 ` [PATCH v4 08/17] x86/insn-eval: Add functions to get default operand and address sizes Ricardo Neri
2017-02-23  6:36 ` [PATCH v4 09/17] x86/insn-eval: Do not use R/EBP as base if mod in ModRM is zero Ricardo Neri
2017-02-23  6:36 ` [PATCH v4 10/17] insn/eval: Incorporate segment base in address computation Ricardo Neri
2017-02-23  6:37 ` [PATCH v4 11/17] x86/insn-eval: Add support to resolve 16-bit addressing encodings Ricardo Neri
2017-02-23  6:37 ` [PATCH v4 12/17] x86/cpufeature: Add User-Mode Instruction Prevention definitions Ricardo Neri
2017-02-23  6:37 ` [PATCH v4 13/17] x86: Add emulation code for UMIP instructions Ricardo Neri
2017-02-23  6:37 ` [PATCH v4 14/17] x86/umip: Force a page fault when unable to copy emulated result to user Ricardo Neri
2017-02-23  6:37 ` [PATCH v4 15/17] x86/traps: Fixup general protection faults caused by UMIP Ricardo Neri
2017-02-23  9:27   ` Peter Zijlstra
2017-02-23 22:15     ` Ricardo Neri
2017-02-24 19:11       ` Andy Lutomirski
2017-02-24 19:36         ` Ricardo Neri
2017-02-24 19:45           ` H. Peter Anvin
2017-02-23  6:37 ` [PATCH v4 16/17] x86: Enable User-Mode Instruction Prevention Ricardo Neri
2017-02-23  6:37 ` [PATCH v4 17/17] selftests/x86: Add tests for " Ricardo Neri

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170223063706.71554-6-ricardo.neri-calderon@linux.intel.com \
    --to=ricardo.neri-calderon@linux.intel.com \
    --cc=akpm@linux-foundation.org \
    --cc=bp@suse.de \
    --cc=brgerst@gmail.com \
    --cc=cmetcalf@mellanox.com \
    --cc=corbet@lwn.net \
    --cc=dave.hansen@linux.intel.com \
    --cc=fenghua.yu@intel.com \
    --cc=hpa@zytor.com \
    --cc=jslaby@suse.cz \
    --cc=julliard@winehq.org \
    --cc=liang.z.li@intel.com \
    --cc=linux-kernel@vger.kern \
    --cc=luto@kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=mingo@redhat.com \
    --cc=mst@redhat.com \
    --cc=paul.gortmaker@windriver.com \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=ravi.v.shankar@intel.com \
    --cc=ray.huang@amd.com \
    --cc=shuah@kernel.org \
    --cc=slaoub@gmail.com \
    --cc=stsp@list.ru \
    --cc=tglx@linutronix.de \
    --cc=vbabka@suse.cz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox