From: Jakub LipovĂ˝ <[email protected]> In 64-bit mode, loading a null selector into SS raises #GP(0) if CPL = 3, or if CPL < 3 and CPL != RPL. helper_load_seg() only implemented the first case: the null-selector path never examined the selector's RPL, so a null selector with non-zero RPL (such as 0x0003) loaded successfully at CPL < 3.
This was caught by test_sreg() in kvm-unit-tests x86/emulator64.c, which additionally fails its subsequent non-null check because the wrongly succeeded load leaves 3 in SS. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/4204 Cc: [email protected] Signed-off-by: Jakub LipovĂ˝ <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Bonzini <[email protected]> --- target/i386/tcg/seg_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c index 6d424349a58..cad19f9ca6b 100644 --- a/target/i386/tcg/seg_helper.c +++ b/target/i386/tcg/seg_helper.c @@ -1411,11 +1411,12 @@ void helper_load_seg(CPUX86State *env, int seg_reg, int selector) selector &= 0xffff; cpl = env->hflags & HF_CPL_MASK; + rpl = selector & 3; if ((selector & 0xfffc) == 0) { /* null selector case */ if (seg_reg == R_SS #ifdef TARGET_X86_64 - && (!(env->hflags & HF_CS64_MASK) || cpl == 3) + && (!(env->hflags & HF_CS64_MASK) || cpl == 3 || cpl != rpl) #endif ) { raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); @@ -1439,7 +1440,6 @@ void helper_load_seg(CPUX86State *env, int seg_reg, int selector) if (!(e2 & DESC_S_MASK)) { raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC()); } - rpl = selector & 3; dpl = (e2 >> DESC_DPL_SHIFT) & 3; if (seg_reg == R_SS) { /* must be writable segment */ -- 2.55.0
