[PATCH v7 17/26] x86/insn-eval: Handle 32-bit address encodings in virtual-8086 mode

Ricardo Neri <[email protected]>
Newsgroups gmane.linux.msdos.general,gmane.linux.kernel,gmane.comp.emulators.wine.devel
Message-ID <[email protected]>
It is possible to utilize 32-bit address encodings in virtual-8086 mode via
an address override instruction prefix. However, the range of 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 <[email protected]>
Cc: Adam Buchbinder <[email protected]>
Cc: Colin Ian King <[email protected]>
Cc: Lorenzo Stoakes <[email protected]>
Cc: Qiaowei Ren <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Adrian Hunter <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: Thomas Garnier <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: Ravi V. Shankar <[email protected]>
Cc: [email protected]
Signed-off-by: Ricardo Neri <[email protected]>
---
 arch/x86/lib/insn-eval.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index c7c1239..9822061 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -848,6 +848,12 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 		linear_addr &= 0xffffffff;
 
 	/*
+	 * 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) && (linear_addr & ~0xffff))
+		goto out_err;
+	/*
 	 * Make sure the effective address is within the limits of the
 	 * segment. In long mode, the limit is -1L. Thus, the second part
 	 * of the check always succeeds.
@@ -857,6 +863,10 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 
 	linear_addr += seg_base_addr;
 
+	/* Limit linear address to 20 bits */
+	if (v8086_mode(regs))
+		linear_addr &= 0xfffff;
+
 	return (void __user *)linear_addr;
 out_err:
 	return (void __user *)-1;
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-msdos" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.