summaryrefslogtreecommitdiff
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/lib/insn-eval.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index 1ac39737826b..ef102db43289 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;
}