[PATCH] target/i386/tcg: raise #GP(0) on null SS load with RPL != CPL

Jakub Lipový posted 1 patch 1 month, 1 week ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260818164414.245189-1-lipovyjakub@tillia.cz
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Richard Henderson <richard.henderson@linaro.org>
target/i386/tcg/seg_helper.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
[PATCH] target/i386/tcg: raise #GP(0) on null SS load with RPL != CPL
Posted by Jakub Lipový 1 month, 1 week ago
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: qemu-stable@nongnu.org
Signed-off-by: Jakub Lipový <lipovyjakub@tillia.cz>
---
All three SS related checks in x86/emulator64.c's test_sreg() now pass
under TCG.

I have not added an in-tree test case to verify this, as this case
requires CPL manipulations that tests/tcg doesn't seem to be able to
easily do. The behavior is covered by test_sreg() in kvm-unit-tests.
Happy to add one if preferred.

 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 d5c174b7fd..36e3ae3b55 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


Re: [PATCH] target/i386/tcg: raise #GP(0) on null SS load with RPL != CPL
Posted by Jakub Lipový 1 week, 4 days ago
Ping.

https://lore.kernel.org/qemu-devel/20260818164414.245189-1-lipovyjakub@tillia.cz/

Still applies cleanly to current master (5f664cd3). Re-tested and
all three SS checks in kvm-unit-tests test_sreg() pass under TCG,
while two fail without the patch.

Thanks,
Jakub