qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug 1857640] [NEW] qemu-system-i386 registers clobbered after gdb set d


From: Marek Dolata
Subject: [Bug 1857640] [NEW] qemu-system-i386 registers clobbered after gdb set due to k_gs_base bug in gdbstub
Date: Thu, 26 Dec 2019 22:42:44 -0000

Public bug reported:

Due to a bug in /target/i386/gdbstub.c, setting registers in gdb causes
the ones following k_gs_base to get clobbered.

I'm using qemu version 4.2.50 on an msys64 and start qemu's i386 with a
gdb server.

$ qemu-system-i386 -version
QEMU emulator version 4.2.50 (v4.2.0-363-gdd5b0f9549-dirty)
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers

$ qemu-system-i386 -gdb tcp::29096 -S
C:\msys64\usr\local\qemu-system-i386.exe: invalid accelerator kvm
C:\msys64\usr\local\qemu-system-i386.exe: falling back to tcg


I start a gdb client, connect to the server, display the register state, set 
k_gs_base, display the register state again, and notice an issue. (Setting 
other registers also clobbers the ones after k_gs_base).

$ gdb -q
(gdb) target remote :29096
...
(gdb) info regs
...
gs_base        0x0      0
k_gs_base      0x0      0
cr0            0x60000010       [ CD NW ET ]
cr2            0x0      0
...
(gdb) set $k_gs_base = 0x41414141
(gdb) info regs
...
gs_base        0x0      0
k_gs_base      0x0      0
cr0            0x41414151       [ CD WP ET PE ]
cr2            0x60000010       1610612752
...


In the gdbstub code, I notice that the read and write functions are not 
symmetric for IDX_SEG_REGS + 8, which corresponds to k_gs_base.

$ cat /usr/local/src/qemu-4.2.0/target/i386/gdbstub.c
...
int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
{
...
        case IDX_SEG_REGS + 8:
#ifdef TARGET_X86_64
            if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
                return gdb_get_reg64(mem_buf, env->kernelgsbase);
            }
            return gdb_get_reg32(mem_buf, env->kernelgsbase);
#else
            return gdb_get_reg32(mem_buf, 0);
#endif
...
}
...
int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
...
#ifdef TARGET_X86_64
        case IDX_SEG_REGS + 8:
            if (env->hflags & HF_CS64_MASK) {
                env->kernelgsbase = ldq_p(mem_buf);
                return 8;
            }
            env->kernelgsbase = ldl_p(mem_buf);
            return 4;
#endif
...
}
...


I change the write function, rebuild, and verify that the issue is resolved.

$ cat /usr/local/src/qemu-4.2.0/target/i386/gdbstub.c
int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
...
        case IDX_SEG_REGS + 8:
#ifdef TARGET_X86_64
            if (env->hflags & HF_CS64_MASK) {
                env->kernelgsbase = ldq_p(mem_buf);
                return 8;
            }
            env->kernelgsbase = ldl_p(mem_buf);
            return 4;
#else
            return 4;
#endif
...
}
...

$ make
...
$ make install
...

$ qemu-system-i386 -gdb tcp::29096 -S

$ gdb -q
(gdb) target remote :29096
...
(gdb) info regs
...
gs_base        0x0      0
k_gs_base      0x0      0
cr0            0x60000010       [ CD NW ET ]
cr2            0x0      0
...
(gdb) set $k_gs_base = 0x41414141
(gdb) info regs
...
gs_base        0x0      0
k_gs_base      0x0      0
cr0            0x60000010       [ CD NW ET ]
cr2            0x0      0
...


I'll submit the patch below.

$ diff gdbstub.c gdbstub.c.bkp
353d352
<         case IDX_SEG_REGS + 8:
354a354
>         case IDX_SEG_REGS + 8:
362,363d361
< #else
<             return 4;

** Affects: qemu
     Importance: Undecided
         Status: New

** Summary changed:

- registers clobbered after set in qemu-system-i386 due to k_gs_base
+ qemu-system-i386 registers clobbered after gdb set due to k_gs_base bug in 
gdbstub

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1857640

Title:
  qemu-system-i386 registers clobbered after gdb set due to k_gs_base
  bug in gdbstub

Status in QEMU:
  New

Bug description:
  Due to a bug in /target/i386/gdbstub.c, setting registers in gdb
  causes the ones following k_gs_base to get clobbered.

  I'm using qemu version 4.2.50 on an msys64 and start qemu's i386 with
  a gdb server.

  $ qemu-system-i386 -version
  QEMU emulator version 4.2.50 (v4.2.0-363-gdd5b0f9549-dirty)
  Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers

  $ qemu-system-i386 -gdb tcp::29096 -S
  C:\msys64\usr\local\qemu-system-i386.exe: invalid accelerator kvm
  C:\msys64\usr\local\qemu-system-i386.exe: falling back to tcg

  
  I start a gdb client, connect to the server, display the register state, set 
k_gs_base, display the register state again, and notice an issue. (Setting 
other registers also clobbers the ones after k_gs_base).

  $ gdb -q
  (gdb) target remote :29096
  ...
  (gdb) info regs
  ...
  gs_base        0x0      0
  k_gs_base      0x0      0
  cr0            0x60000010       [ CD NW ET ]
  cr2            0x0      0
  ...
  (gdb) set $k_gs_base = 0x41414141
  (gdb) info regs
  ...
  gs_base        0x0      0
  k_gs_base      0x0      0
  cr0            0x41414151       [ CD WP ET PE ]
  cr2            0x60000010       1610612752
  ...

  
  In the gdbstub code, I notice that the read and write functions are not 
symmetric for IDX_SEG_REGS + 8, which corresponds to k_gs_base.

  $ cat /usr/local/src/qemu-4.2.0/target/i386/gdbstub.c
  ...
  int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
  {
  ...
          case IDX_SEG_REGS + 8:
  #ifdef TARGET_X86_64
              if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
                  return gdb_get_reg64(mem_buf, env->kernelgsbase);
              }
              return gdb_get_reg32(mem_buf, env->kernelgsbase);
  #else
              return gdb_get_reg32(mem_buf, 0);
  #endif
  ...
  }
  ...
  int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
  {
  ...
  #ifdef TARGET_X86_64
          case IDX_SEG_REGS + 8:
              if (env->hflags & HF_CS64_MASK) {
                  env->kernelgsbase = ldq_p(mem_buf);
                  return 8;
              }
              env->kernelgsbase = ldl_p(mem_buf);
              return 4;
  #endif
  ...
  }
  ...

  
  I change the write function, rebuild, and verify that the issue is resolved.

  $ cat /usr/local/src/qemu-4.2.0/target/i386/gdbstub.c
  int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
  {
  ...
          case IDX_SEG_REGS + 8:
  #ifdef TARGET_X86_64
              if (env->hflags & HF_CS64_MASK) {
                  env->kernelgsbase = ldq_p(mem_buf);
                  return 8;
              }
              env->kernelgsbase = ldl_p(mem_buf);
              return 4;
  #else
              return 4;
  #endif
  ...
  }
  ...

  $ make
  ...
  $ make install
  ...

  $ qemu-system-i386 -gdb tcp::29096 -S

  $ gdb -q
  (gdb) target remote :29096
  ...
  (gdb) info regs
  ...
  gs_base        0x0      0
  k_gs_base      0x0      0
  cr0            0x60000010       [ CD NW ET ]
  cr2            0x0      0
  ...
  (gdb) set $k_gs_base = 0x41414141
  (gdb) info regs
  ...
  gs_base        0x0      0
  k_gs_base      0x0      0
  cr0            0x60000010       [ CD NW ET ]
  cr2            0x0      0
  ...

  
  I'll submit the patch below.

  $ diff gdbstub.c gdbstub.c.bkp
  353d352
  <         case IDX_SEG_REGS + 8:
  354a354
  >         case IDX_SEG_REGS + 8:
  362,363d361
  < #else
  <             return 4;

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1857640/+subscriptions



reply via email to

[Prev in Thread] Current Thread [Next in Thread]