From e4b66a0ef3edc7d0ef7dd783c8ecaccd09eb4c28 Mon Sep 17 00:00:00 2001 From: Andrew Oates Date: Sat, 25 Aug 2018 03:30:54 -0400 Subject: [PATCH] target-i386: fix segment limit check in ljmp The current implementation has three bugs, * segment limits are not enforced in protected mode if the L bit is set in the target segment descriptor * segment limits are not enforced in compatibility mode (ljmp to 32-bit code segment in long mode) * #GP(new_cs) is generated rather than #GP(0) Now the segment limits are enforced if we're not in long mode OR the target code segment doesn't have the L bit set. Backports commit db7196db5d5d932f388643baae6835f8dcda6921 from qemu --- qemu/target/i386/seg_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu/target/i386/seg_helper.c b/qemu/target/i386/seg_helper.c index eabf8480..c446add7 100644 --- a/qemu/target/i386/seg_helper.c +++ b/qemu/target/i386/seg_helper.c @@ -1633,8 +1633,8 @@ void helper_ljmp_protected(CPUX86State *env, int new_cs, target_ulong new_eip, } limit = get_seg_limit(e1, e2); if (new_eip > limit && - !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK)) { - raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC()); + (!(env->hflags & HF_LMA_MASK) || !(e2 & DESC_L_MASK))) { + raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); } cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl, get_seg_base(e1, e2), limit, e2);