diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index 1ac39737826bbf63dbb36f2891167a3d2ee5fef8..ef102db43289c106a1375f82b34922adec8c661c 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -1041,6 +1041,13 @@ static void __user *get_addr_ref_32(struct insn *insn, struct pt_regs *regs)
 	if (!user_64bit_mode(regs) && ((unsigned int)eff_addr > seg_limit))
 		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
@@ -1048,6 +1055,10 @@ static void __user *get_addr_ref_32(struct insn *insn, struct pt_regs *regs)
 	 */
 	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;
 }