diff options
author | Paul Gortmaker <paul.gortmaker@windriver.com> | 2018-08-02 12:53:50 -0400 |
---|---|---|
committer | Paul Gortmaker <paul.gortmaker@windriver.com> | 2018-08-02 12:53:50 -0400 |
commit | 000447dc0d892a41d1f7c9989885cde9cb95a86f (patch) | |
tree | 90c39aed07e2d29f96ce21d7cbf10c75a1f86602 | |
parent | c145b880adcfb776561e3fe5417c805a35878864 (diff) | |
download | longterm-queue-4.12-000447dc0d892a41d1f7c9989885cde9cb95a86f.tar.gz |
x86: drop insn commit; breaks build
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-rw-r--r-- | queue/series | 1 | ||||
-rw-r--r-- | queue/x86-insn-eval-Add-utility-functions-to-get-segment-s.patch | 463 |
2 files changed, 0 insertions, 464 deletions
diff --git a/queue/series b/queue/series index 42f9a28..c0ba19c 100644 --- a/queue/series +++ b/queue/series @@ -50,7 +50,6 @@ bpf-s390x-do-not-reload-skb-pointers-in-non-skb-cont.patch bpf-ppc64-do-not-reload-skb-pointers-in-non-skb-cont.patch bpf-sparc-fix-usage-of-wrong-reg-for-load_skb_regs-a.patch bpf-fix-incorrect-sign-extension-in-check_alu_op.patch -x86-insn-eval-Add-utility-functions-to-get-segment-s.patch ACPI-APEI-ERST-Fix-missing-error-handling-in-erst_re.patch acpi-nfit-fix-health-event-notification.patch crypto-mcryptd-protect-the-per-CPU-queue-with-a-lock.patch diff --git a/queue/x86-insn-eval-Add-utility-functions-to-get-segment-s.patch b/queue/x86-insn-eval-Add-utility-functions-to-get-segment-s.patch deleted file mode 100644 index 2fe51ef..0000000 --- a/queue/x86-insn-eval-Add-utility-functions-to-get-segment-s.patch +++ /dev/null @@ -1,463 +0,0 @@ -From c3719f8bb7ae0249b00882e9f8a9b3989d4f367c Mon Sep 17 00:00:00 2001 -From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com> -Date: Fri, 27 Oct 2017 13:25:40 -0700 -Subject: [PATCH] x86/insn-eval: Add utility functions to get segment selector - -commit 32d0b95300db03c2b23b2ea2c94769a4a138e79d upstream. - -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, the segment base address will be zero as in USER_DS/USER32_DS. -However, it may be possible that a user space program defines its own -segments via a local descriptor table. In such a case, the segment base -address may not be zero. Thus, the segment base address is needed to -calculate correctly the linear address. - -If running in protected mode, the segment selector to be used when -computing a linear address is determined by either any of segment override -prefixes in the instruction or inferred from the registers involved in the -computation of the effective address; in that order. Also, there are cases -when the segment override prefixes shall be ignored (i.e., code segments -are always selected by the CS segment register; string instructions always -use the ES segment register when using rDI register as operand). In long -mode, segment registers are ignored, except for FS and GS. In these two -cases, base addresses are obtained from the respective MSRs. - -For clarity, this process can be split into four steps (and an equal -number of functions): determine if segment prefixes overrides can be used; -parse the segment override prefixes, and use them if found; if not found -or cannot be used, use the default segment registers associated with the -operand registers. Once the segment register to use has been identified, -read its value to obtain the segment selector. - -The method to obtain the segment selector depends on several factors. In -32-bit builds, segment selectors are saved into a pt_regs structure -when switching to kernel mode. The same is also true for virtual-8086 -mode. In 64-bit builds, segmentation is mostly ignored, except when -running a program in 32-bit legacy mode. In this case, CS and SS can be -obtained from pt_regs. DS, ES, FS and GS can be read directly from -the respective segment registers. - -In order to identify the segment registers, a new set of #defines is -introduced. It also includes two special identifiers. One of them -indicates when the default segment register associated with instruction -operands shall be used. Another one indicates that the contents of the -segment register shall be ignored; this identifier is used when in long -mode. - -Improvements-by: Borislav Petkov <bp@suse.de> -Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com> -Signed-off-by: Thomas Gleixner <tglx@linutronix.de> -Reviewed-by: Borislav Petkov <bp@suse.de> -Cc: "Michael S. Tsirkin" <mst@redhat.com> -Cc: Peter Zijlstra <peterz@infradead.org> -Cc: Dave Hansen <dave.hansen@linux.intel.com> -Cc: ricardo.neri@intel.com -Cc: Adrian Hunter <adrian.hunter@intel.com> -Cc: Paul Gortmaker <paul.gortmaker@windriver.com> -Cc: Huang Rui <ray.huang@amd.com> -Cc: Qiaowei Ren <qiaowei.ren@intel.com> -Cc: Shuah Khan <shuah@kernel.org> -Cc: Kees Cook <keescook@chromium.org> -Cc: Jonathan Corbet <corbet@lwn.net> -Cc: Jiri Slaby <jslaby@suse.cz> -Cc: Dmitry Vyukov <dvyukov@google.com> -Cc: "Ravi V. Shankar" <ravi.v.shankar@intel.com> -Cc: Chris Metcalf <cmetcalf@mellanox.com> -Cc: Brian Gerst <brgerst@gmail.com> -Cc: Arnaldo Carvalho de Melo <acme@redhat.com> -Cc: Andy Lutomirski <luto@kernel.org> -Cc: Colin Ian King <colin.king@canonical.com> -Cc: Chen Yucong <slaoub@gmail.com> -Cc: Adam Buchbinder <adam.buchbinder@gmail.com> -Cc: Vlastimil Babka <vbabka@suse.cz> -Cc: Lorenzo Stoakes <lstoakes@gmail.com> -Cc: Masami Hiramatsu <mhiramat@kernel.org> -Cc: Paolo Bonzini <pbonzini@redhat.com> -Cc: Andrew Morton <akpm@linux-foundation.org> -Cc: Thomas Garnier <thgarnie@google.com> -Link: https://lkml.kernel.org/r/1509135945-13762-14-git-send-email-ricardo.neri-calderon@linux.intel.com -Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> - -diff --git a/arch/x86/include/asm/inat.h b/arch/x86/include/asm/inat.h -index 02aff0867211..1c78580e58be 100644 ---- a/arch/x86/include/asm/inat.h -+++ b/arch/x86/include/asm/inat.h -@@ -97,6 +97,16 @@ - #define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM) - #define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS) - -+/* Identifiers for segment registers */ -+#define INAT_SEG_REG_IGNORE 0 -+#define INAT_SEG_REG_DEFAULT 1 -+#define INAT_SEG_REG_CS 2 -+#define INAT_SEG_REG_SS 3 -+#define INAT_SEG_REG_DS 4 -+#define INAT_SEG_REG_ES 5 -+#define INAT_SEG_REG_FS 6 -+#define INAT_SEG_REG_GS 7 -+ - /* Attribute search APIs */ - extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode); - extern int inat_get_last_prefix_id(insn_byte_t last_pfx); -diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c -index 405ffeb1c382..e5ef85a37102 100644 ---- a/arch/x86/lib/insn-eval.c -+++ b/arch/x86/lib/insn-eval.c -@@ -9,6 +9,7 @@ - #include <asm/inat.h> - #include <asm/insn.h> - #include <asm/insn-eval.h> -+#include <asm/vm86.h> - - #undef pr_fmt - #define pr_fmt(fmt) "insn: " fmt -@@ -19,6 +20,345 @@ enum reg_type { - REG_TYPE_BASE, - }; - -+/** -+ * get_seg_reg_override_idx() - obtain segment register override index -+ * @insn: Valid instruction with segment override prefixes -+ * -+ * Inspect the instruction prefixes in @insn and find segment overrides, if any. -+ * -+ * Returns: -+ * -+ * A constant identifying the segment register to use, among CS, SS, DS, -+ * ES, FS, or GS. INAT_SEG_REG_DEFAULT is returned if no segment override -+ * prefixes were found. -+ * -+ * -EINVAL in case of error. -+ */ -+static int get_seg_reg_override_idx(struct insn *insn) -+{ -+ int idx = INAT_SEG_REG_DEFAULT; -+ int num_overrides = 0, i; -+ -+ insn_get_prefixes(insn); -+ -+ /* Look for any segment override prefixes. */ -+ for (i = 0; i < insn->prefixes.nbytes; i++) { -+ insn_attr_t attr; -+ -+ attr = inat_get_opcode_attribute(insn->prefixes.bytes[i]); -+ switch (attr) { -+ case INAT_MAKE_PREFIX(INAT_PFX_CS): -+ idx = INAT_SEG_REG_CS; -+ num_overrides++; -+ break; -+ case INAT_MAKE_PREFIX(INAT_PFX_SS): -+ idx = INAT_SEG_REG_SS; -+ num_overrides++; -+ break; -+ case INAT_MAKE_PREFIX(INAT_PFX_DS): -+ idx = INAT_SEG_REG_DS; -+ num_overrides++; -+ break; -+ case INAT_MAKE_PREFIX(INAT_PFX_ES): -+ idx = INAT_SEG_REG_ES; -+ num_overrides++; -+ break; -+ case INAT_MAKE_PREFIX(INAT_PFX_FS): -+ idx = INAT_SEG_REG_FS; -+ num_overrides++; -+ break; -+ case INAT_MAKE_PREFIX(INAT_PFX_GS): -+ idx = INAT_SEG_REG_GS; -+ num_overrides++; -+ break; -+ /* No default action needed. */ -+ } -+ } -+ -+ /* More than one segment override prefix leads to undefined behavior. */ -+ if (num_overrides > 1) -+ return -EINVAL; -+ -+ return idx; -+} -+ -+/** -+ * check_seg_overrides() - check if segment override prefixes are allowed -+ * @insn: Valid instruction with segment override prefixes -+ * @regoff: Operand offset, in pt_regs, for which the check is performed -+ * -+ * For a particular register used in register-indirect addressing, determine if -+ * segment override prefixes can be used. Specifically, no overrides are allowed -+ * for rDI if used with a string instruction. -+ * -+ * Returns: -+ * -+ * True if segment override prefixes can be used with the register indicated -+ * in @regoff. False if otherwise. -+ */ -+static bool check_seg_overrides(struct insn *insn, int regoff) -+{ -+ if (regoff == offsetof(struct pt_regs, di) && is_string_insn(insn)) -+ return false; -+ -+ return true; -+} -+ -+/** -+ * resolve_default_seg() - resolve default segment register index for an operand -+ * @insn: Instruction with opcode and address size. Must be valid. -+ * @regs: Register values as seen when entering kernel mode -+ * @off: Operand offset, in pt_regs, for which resolution is needed -+ * -+ * Resolve the default segment register index associated with the instruction -+ * operand register indicated by @off. Such index is resolved based on defaults -+ * described in the Intel Software Development Manual. -+ * -+ * Returns: -+ * -+ * If in protected mode, a constant identifying the segment register to use, -+ * among CS, SS, ES or DS. If in long mode, INAT_SEG_REG_IGNORE. -+ * -+ * -EINVAL in case of error. -+ */ -+static int resolve_default_seg(struct insn *insn, struct pt_regs *regs, int off) -+{ -+ if (user_64bit_mode(regs)) -+ return INAT_SEG_REG_IGNORE; -+ /* -+ * Resolve the default segment register as described in Section 3.7.4 -+ * of the Intel Software Development Manual Vol. 1: -+ * -+ * + DS for all references involving r[ABCD]X, and rSI. -+ * + If used in a string instruction, ES for rDI. Otherwise, DS. -+ * + AX, CX and DX are not valid register operands in 16-bit address -+ * encodings but are valid for 32-bit and 64-bit encodings. -+ * + -EDOM is reserved to identify for cases in which no register -+ * is used (i.e., displacement-only addressing). Use DS. -+ * + SS for rSP or rBP. -+ * + CS for rIP. -+ */ -+ -+ switch (off) { -+ case offsetof(struct pt_regs, ax): -+ case offsetof(struct pt_regs, cx): -+ case offsetof(struct pt_regs, dx): -+ /* Need insn to verify address size. */ -+ if (insn->addr_bytes == 2) -+ return -EINVAL; -+ -+ case -EDOM: -+ case offsetof(struct pt_regs, bx): -+ case offsetof(struct pt_regs, si): -+ return INAT_SEG_REG_DS; -+ -+ case offsetof(struct pt_regs, di): -+ if (is_string_insn(insn)) -+ return INAT_SEG_REG_ES; -+ return INAT_SEG_REG_DS; -+ -+ case offsetof(struct pt_regs, bp): -+ case offsetof(struct pt_regs, sp): -+ return INAT_SEG_REG_SS; -+ -+ case offsetof(struct pt_regs, ip): -+ return INAT_SEG_REG_CS; -+ -+ default: -+ return -EINVAL; -+ } -+} -+ -+/** -+ * resolve_seg_reg() - obtain segment register index -+ * @insn: Instruction with operands -+ * @regs: Register values as seen when entering kernel mode -+ * @regoff: Operand offset, in pt_regs, used to deterimine segment register -+ * -+ * Determine the segment register associated with the operands and, if -+ * applicable, prefixes and the instruction pointed by @insn. -+ * -+ * The segment register associated to an operand used in register-indirect -+ * addressing depends on: -+ * -+ * a) Whether running in long mode (in such a case segments are ignored, except -+ * if FS or GS are used). -+ * -+ * b) Whether segment override prefixes can be used. Certain instructions and -+ * registers do not allow override prefixes. -+ * -+ * c) Whether segment overrides prefixes are found in the instruction prefixes. -+ * -+ * d) If there are not segment override prefixes or they cannot be used, the -+ * default segment register associated with the operand register is used. -+ * -+ * The function checks first if segment override prefixes can be used with the -+ * operand indicated by @regoff. If allowed, obtain such overridden segment -+ * register index. Lastly, if not prefixes were found or cannot be used, resolve -+ * the segment register index to use based on the defaults described in the -+ * Intel documentation. In long mode, all segment register indexes will be -+ * ignored, except if overrides were found for FS or GS. All these operations -+ * are done using helper functions. -+ * -+ * The operand register, @regoff, is represented as the offset from the base of -+ * pt_regs. -+ * -+ * As stated, the main use of this function is to determine the segment register -+ * index based on the instruction, its operands and prefixes. Hence, @insn -+ * must be valid. However, if @regoff indicates rIP, we don't need to inspect -+ * @insn at all as in this case CS is used in all cases. This case is checked -+ * before proceeding further. -+ * -+ * Please note that this function does not return the value in the segment -+ * register (i.e., the segment selector) but our defined index. The segment -+ * selector needs to be obtained using get_segment_selector() and passing the -+ * segment register index resolved by this function. -+ * -+ * Returns: -+ * -+ * An index identifying the segment register to use, among CS, SS, DS, -+ * ES, FS, or GS. INAT_SEG_REG_IGNORE is returned if running in long mode. -+ * -+ * -EINVAL in case of error. -+ */ -+static int resolve_seg_reg(struct insn *insn, struct pt_regs *regs, int regoff) -+{ -+ int idx; -+ -+ /* -+ * In the unlikely event of having to resolve the segment register -+ * index for rIP, do it first. Segment override prefixes should not -+ * be used. Hence, it is not necessary to inspect the instruction, -+ * which may be invalid at this point. -+ */ -+ if (regoff == offsetof(struct pt_regs, ip)) { -+ if (user_64bit_mode(regs)) -+ return INAT_SEG_REG_IGNORE; -+ else -+ return INAT_SEG_REG_CS; -+ } -+ -+ if (!insn) -+ return -EINVAL; -+ -+ if (!check_seg_overrides(insn, regoff)) -+ return resolve_default_seg(insn, regs, regoff); -+ -+ idx = get_seg_reg_override_idx(insn); -+ if (idx < 0) -+ return idx; -+ -+ if (idx == INAT_SEG_REG_DEFAULT) -+ return resolve_default_seg(insn, regs, regoff); -+ -+ /* -+ * In long mode, segment override prefixes are ignored, except for -+ * overrides for FS and GS. -+ */ -+ if (user_64bit_mode(regs)) { -+ if (idx != INAT_SEG_REG_FS && -+ idx != INAT_SEG_REG_GS) -+ idx = INAT_SEG_REG_IGNORE; -+ } -+ -+ return idx; -+} -+ -+/** -+ * get_segment_selector() - obtain segment selector -+ * @regs: Register values as seen when entering kernel mode -+ * @seg_reg_idx: Segment register index to use -+ * -+ * Obtain the segment selector from any of the CS, SS, DS, ES, FS, GS segment -+ * registers. In CONFIG_X86_32, the segment is obtained from either pt_regs or -+ * kernel_vm86_regs as applicable. In CONFIG_X86_64, CS and SS are obtained -+ * from pt_regs. DS, ES, FS and GS are obtained by reading the actual CPU -+ * registers. This done for only for completeness as in CONFIG_X86_64 segment -+ * registers are ignored. -+ * -+ * Returns: -+ * -+ * Value of the segment selector, including null when running in -+ * long mode. -+ * -+ * -EINVAL on error. -+ */ -+static short get_segment_selector(struct pt_regs *regs, int seg_reg_idx) -+{ -+#ifdef CONFIG_X86_64 -+ unsigned short sel; -+ -+ switch (seg_reg_idx) { -+ case INAT_SEG_REG_IGNORE: -+ return 0; -+ case INAT_SEG_REG_CS: -+ return (unsigned short)(regs->cs & 0xffff); -+ case INAT_SEG_REG_SS: -+ return (unsigned short)(regs->ss & 0xffff); -+ case INAT_SEG_REG_DS: -+ savesegment(ds, sel); -+ return sel; -+ case INAT_SEG_REG_ES: -+ savesegment(es, sel); -+ return sel; -+ case INAT_SEG_REG_FS: -+ savesegment(fs, sel); -+ return sel; -+ case INAT_SEG_REG_GS: -+ savesegment(gs, sel); -+ return sel; -+ default: -+ return -EINVAL; -+ } -+#else /* CONFIG_X86_32 */ -+ struct kernel_vm86_regs *vm86regs = (struct kernel_vm86_regs *)regs; -+ -+ if (v8086_mode(regs)) { -+ switch (seg_reg_idx) { -+ case INAT_SEG_REG_CS: -+ return (unsigned short)(regs->cs & 0xffff); -+ case INAT_SEG_REG_SS: -+ return (unsigned short)(regs->ss & 0xffff); -+ case INAT_SEG_REG_DS: -+ return vm86regs->ds; -+ case INAT_SEG_REG_ES: -+ return vm86regs->es; -+ case INAT_SEG_REG_FS: -+ return vm86regs->fs; -+ case INAT_SEG_REG_GS: -+ return vm86regs->gs; -+ case INAT_SEG_REG_IGNORE: -+ /* fall through */ -+ default: -+ return -EINVAL; -+ } -+ } -+ -+ switch (seg_reg_idx) { -+ case INAT_SEG_REG_CS: -+ return (unsigned short)(regs->cs & 0xffff); -+ case INAT_SEG_REG_SS: -+ return (unsigned short)(regs->ss & 0xffff); -+ case INAT_SEG_REG_DS: -+ return (unsigned short)(regs->ds & 0xffff); -+ case INAT_SEG_REG_ES: -+ return (unsigned short)(regs->es & 0xffff); -+ case INAT_SEG_REG_FS: -+ return (unsigned short)(regs->fs & 0xffff); -+ case INAT_SEG_REG_GS: -+ /* -+ * GS may or may not be in regs as per CONFIG_X86_32_LAZY_GS. -+ * The macro below takes care of both cases. -+ */ -+ return get_user_gs(regs); -+ case INAT_SEG_REG_IGNORE: -+ /* fall through */ -+ default: -+ return -EINVAL; -+ } -+#endif /* CONFIG_X86_64 */ -+} -+ - static int get_reg_offset(struct insn *insn, struct pt_regs *regs, - enum reg_type type) - { --- -2.15.0 - |