[PATCH] kgdb: Fix buffer overflow in the qRcmd packet handler

Fang Xieyan posted 1 patch 1 week, 1 day ago
kernel/debug/gdbstub.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH] kgdb: Fix buffer overflow in the qRcmd packet handler
Posted by Fang Xieyan 1 week, 1 day ago
gdb_cmd_query() decodes the hex payload of a qRcmd packet (the GDB
"monitor" command passthrough to kdb) into remcom_out_buffer and hands
it to kdb_parse(). It sizes the decode with strlen() of the payload:

	int len = strlen(remcom_in_buffer + 6);
	...
	kgdb_hex2mem(remcom_in_buffer + 6,
		     remcom_out_buffer, len);
	len = len / 2;

kgdb_hex2mem() takes count as the number of bytes to produce and
decodes them in place at buf, reading and writing 2 * count bytes
there. len here is the hex character count, twice the decoded size,
so the decode runs over 2 * len bytes at remcom_in_buffer + 6, off
the end of the buffer. On x86 BUFMAX is 1024, so a 256-byte monitor
command (512 hex characters) overruns remcom_in_buffer during the
in-place decode:

  BUG: KASAN: global-out-of-bounds in kgdb_hex2mem+0x131/0x160
  Read of size 1 at addr ffffffff8765ef05 by task sh/1
  ...
  kgdb_hex2mem+0x131/0x160
  gdb_serial_stub+0x16d4/0x3170
  kgdb_cpu_enter+0xb68/0x1520
  ...
  The buggy address belongs to the variable:
   remcom_in_buffer+0x405/0x420

Halve len before the call so kgdb_hex2mem() gets the decoded byte count.
It then reads the len hex characters already in remcom_in_buffer and
writes len / 2 bytes, all inside the buffer, and remcom_out_buffer holds
the same command as before.

Fixes: a0de055cf613 ("kgdb: gdb "monitor" -> kdb passthrough")
Cc: stable@vger.kernel.org
Suggested-by: Douglas Anderson <dianders@chromium.org>
Link: https://lore.kernel.org/all/CAD=FV=V1-gNZ8yTsC+D8inePWv=A+9H09hWJojQf5NRpcNvK+Q@mail.gmail.com/
Assisted-by: Qoder:Qwen3.8-Max
Signed-off-by: Fang Xieyan <fangxy@xiaopeng.com>
---

This is the third in a family of unvalidated-length decodes in the kgdb
gdbstub; the 'm' memread and 'M'/'X' memwrite fixes were sent separately.
Unlike those two, there is no attacker-claimed length field here. len is
the real hex-character count bounded by get_packet(), so the only defect
is passing the hex length instead of half of it to kgdb_hex2mem().
Halving it is sufficient; no separate bounds check is needed.

Reproducer: attach to a kgdboc console, break in, run kdb's "kgdb"
command to switch to gdb mode, then send a qRcmd packet with an even
hex payload of 510 or more characters, e.g. "qRcmd," + "41"*256 on x86.
Before the fix, KASAN reports a global-out-of-bounds read in
kgdb_hex2mem(): the decode runs to remcom_in_buffer+0x405, past
BUFMAX=0x400, and the guest dies. After the fix the decode stays
in-bounds, the command reaches kdb_parse() and the handler answers OK.
The patched run does print kdb_parse()'s own "command buffer overflow,
command ignored" for a 256-byte command; that is kdb's length limit on
the decoded string, not this bug.

Tested on mainline 704340f1cd0d (git describe v7.3-rc3-9-g704340f1cd0d):
x86_64 defconfig plus CONFIG_KGDB_KDB and CONFIG_KASAN_GENERIC, gcc
13.2.0, QEMU under TCG. Both kernels were built from byte-identical
.config files and differ only by this patch.

 kernel/debug/gdbstub.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c
index e271a43..41e344e 100644
--- a/kernel/debug/gdbstub.c
+++ b/kernel/debug/gdbstub.c
@@ -778,9 +778,9 @@ static void gdb_cmd_query(struct kgdb_state *ks)
 				strscpy(remcom_out_buffer, "E01");
 				break;
 			}
+			len = len / 2;
 			kgdb_hex2mem(remcom_in_buffer + 6,
 				     remcom_out_buffer, len);
-			len = len / 2;
 			remcom_out_buffer[len++] = 0;
 
 			kdb_common_init_state(ks);
-- 
2.50.1 (Apple Git-155)
Re: [PATCH] kgdb: Fix buffer overflow in the qRcmd packet handler
Posted by Doug Anderson 1 week, 1 day ago
Hi,

On Wed, Sep 16, 2026 at 8:18 AM Fang Xieyan <fangxy@xiaopeng.com> wrote:
>
> gdb_cmd_query() decodes the hex payload of a qRcmd packet (the GDB
> "monitor" command passthrough to kdb) into remcom_out_buffer and hands
> it to kdb_parse(). It sizes the decode with strlen() of the payload:
>
>         int len = strlen(remcom_in_buffer + 6);
>         ...
>         kgdb_hex2mem(remcom_in_buffer + 6,
>                      remcom_out_buffer, len);
>         len = len / 2;
>
> kgdb_hex2mem() takes count as the number of bytes to produce and
> decodes them in place at buf, reading and writing 2 * count bytes
> there. len here is the hex character count, twice the decoded size,
> so the decode runs over 2 * len bytes at remcom_in_buffer + 6, off
> the end of the buffer. On x86 BUFMAX is 1024, so a 256-byte monitor
> command (512 hex characters) overruns remcom_in_buffer during the
> in-place decode:
>
>   BUG: KASAN: global-out-of-bounds in kgdb_hex2mem+0x131/0x160
>   Read of size 1 at addr ffffffff8765ef05 by task sh/1
>   ...
>   kgdb_hex2mem+0x131/0x160
>   gdb_serial_stub+0x16d4/0x3170
>   kgdb_cpu_enter+0xb68/0x1520
>   ...
>   The buggy address belongs to the variable:
>    remcom_in_buffer+0x405/0x420
>
> Halve len before the call so kgdb_hex2mem() gets the decoded byte count.
> It then reads the len hex characters already in remcom_in_buffer and
> writes len / 2 bytes, all inside the buffer, and remcom_out_buffer holds
> the same command as before.
>
> Fixes: a0de055cf613 ("kgdb: gdb "monitor" -> kdb passthrough")
> Cc: stable@vger.kernel.org
> Suggested-by: Douglas Anderson <dianders@chromium.org>
> Link: https://lore.kernel.org/all/CAD=FV=V1-gNZ8yTsC+D8inePWv=A+9H09hWJojQf5NRpcNvK+Q@mail.gmail.com/
> Assisted-by: Qoder:Qwen3.8-Max
> Signed-off-by: Fang Xieyan <fangxy@xiaopeng.com>
> ---
>
> This is the third in a family of unvalidated-length decodes in the kgdb
> gdbstub; the 'm' memread and 'M'/'X' memwrite fixes were sent separately.
> Unlike those two, there is no attacker-claimed length field here. len is
> the real hex-character count bounded by get_packet(), so the only defect
> is passing the hex length instead of half of it to kgdb_hex2mem().
> Halving it is sufficient; no separate bounds check is needed.
>
> Reproducer: attach to a kgdboc console, break in, run kdb's "kgdb"
> command to switch to gdb mode, then send a qRcmd packet with an even
> hex payload of 510 or more characters, e.g. "qRcmd," + "41"*256 on x86.
> Before the fix, KASAN reports a global-out-of-bounds read in
> kgdb_hex2mem(): the decode runs to remcom_in_buffer+0x405, past
> BUFMAX=0x400, and the guest dies. After the fix the decode stays
> in-bounds, the command reaches kdb_parse() and the handler answers OK.
> The patched run does print kdb_parse()'s own "command buffer overflow,
> command ignored" for a 256-byte command; that is kdb's length limit on
> the decoded string, not this bug.
>
> Tested on mainline 704340f1cd0d (git describe v7.3-rc3-9-g704340f1cd0d):
> x86_64 defconfig plus CONFIG_KGDB_KDB and CONFIG_KASAN_GENERIC, gcc
> 13.2.0, QEMU under TCG. Both kernels were built from byte-identical
> .config files and differ only by this patch.
>
>  kernel/debug/gdbstub.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Douglas Anderson <dianders@chromium.org>