[PATCH v4 10/17] insn/eval: Incorporate segment base in address computation

Ricardo Neri ricardo.neri-calderon at linux.intel.com
Thu Feb 23 00:36:59 CST 2017


insn_get_addr_ref returns the effective address as defined by the
section 3.7.5.1 Vol 1 of the Intel 64 and IA-32 Architectures Software
Developer's Manual. In order to truly give the linear address, we must
add the effective address to the segment base as described by the segment
descriptor.

In most cases, the base will be 0 if the USER_DS segment is used or if
segmentation is not used. However, the base address is not necessarily
zero if a user programs defines its own segments. This is possible by
using a local descriptor table.

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

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index d6525c2..b3a2fe8 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -523,6 +523,7 @@ static void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 		if (addr_offset < 0)
 			goto out_err;
 		addr = regs_get_register(regs, addr_offset);
+		addr += insn_get_seg_base(regs, insn, addr_offset);
 	} else {
 		if (insn->sib.nbytes) {
 			/*
@@ -551,6 +552,7 @@ static void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 				indx = regs_get_register(regs, indx_offset);
 
 			addr = base + indx * (1 << X86_SIB_SCALE(sib));
+			addr += insn_get_seg_base(regs, insn, base_offset);
 		} else {
 			unsigned char addr_bytes;
 
@@ -575,8 +577,10 @@ static void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 			} else {
 				addr = regs_get_register(regs, addr_offset);
 			}
+			addr += insn_get_seg_base(regs, insn, addr_offset);
 		}
 		addr += insn->displacement.value;
+
 	}
 	return (void __user *)addr;
 out_err:
-- 
2.9.3




More information about the wine-devel mailing list