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

From: Fang Xieyan

Date: Mon Sep 14 2026 - 14:24:26 EST


gdb_cmd_memread() passes the length of the 'm' packet straight to
kgdb_mem2hex(), which hex-encodes the reply into
remcom_out_buffer[BUFMAX] without checking that the reply fits. A
client on the KGDB I/O console can ask for a read of any size, and
the hex encoding runs off the end of the buffer. kgdb_mem2hex() takes
that length as an int count, so 2^31 truncates to a negative value
and copy_from_kernel_nofault() is handed buf + count as its
destination.

On x86 BUFMAX is 1024, so a read of 512 bytes overruns by the single
byte that terminates the hex string:

BUG: KASAN: global-out-of-bounds in kgdb_mem2hex+0x1dd/0x230
Write of size 1 at addr ffffffff87651780 by task sh/1
...
The buggy address belongs to the variable:
remcom_out_buffer+0x400/0x420

Bounds check the length before the hex encoding:

if (length > (BUFMAX - 1) / 2) {
error_packet(remcom_out_buffer, -EINVAL);
return;
}

gdbstub_msg_write() already bounds the count it hex-encodes
against BUFMAX. Reads over the limit never returned valid data,
so an error reply loses nothing.

Fixes: dc7d55270521 ("kgdb: core")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Hawkeye:GLM-5.3-flash
Assisted-by: Qoder:Qwen3.8-Max
Signed-off-by: Fang Xieyan <fangxy@xxxxxxxxxxxx>
---

The scanner is a taint-style review of the packet handlers in
kernel/debug/gdbstub.c. write_mem_msg() ('M' and 'X' packets) trusts
the same length field and looks like the same class of problem; I can
send that separately if there is interest.

Reproducer: attach to a kgdboc console and send an 'm' packet with a
length above (BUFMAX - 1) / 2, e.g. "m<addr>,200" on x86. Before this
change the hex encoding runs off the end of remcom_out_buffer; after
it the stub answers E22 and the guest resumes.

Both cases were run on 704340f1cd0d (v7.3-rc4): x86_64 defconfig plus
CONFIG_KASAN_GENERIC, gcc 13.2.0, QEMU under TCG. The two kernels are
built from byte-identical .config files and differ only by this patch.

Two details of the setup are not obvious. CONFIG_KGDB_KDB has to be
off: dbg_kdb_mode starts at 1, so with kdb built in a sysrq-g break
lands in kdb_stub() and the packet is never parsed.

A minimal over-the-limit length reproduces better than a large one.
copy_from_kernel_nofault() copies through raw asm accessors that KASAN
does not instrument, so length = 0x10000 writes 64 KiB past the buffer
with no report at all and the kernel simply stops answering. length =
0x200 keeps that copy inside the buffer, which leaves the terminating
store as the only out-of-bounds access and gives the report above.

kernel/debug/gdbstub.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c
index e271a43..5774292 100644
--- a/kernel/debug/gdbstub.c
+++ b/kernel/debug/gdbstub.c
@@ -563,6 +563,14 @@ static void gdb_cmd_memread(struct kgdb_state *ks)

if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' &&
kgdb_hex2long(&ptr, &length) > 0) {
+ /*
+ * The hex-encoded reply needs 2 * length + 1 bytes
+ * in remcom_out_buffer[BUFMAX].
+ */
+ if (length > (BUFMAX - 1) / 2) {
+ error_packet(remcom_out_buffer, -EINVAL);
+ return;
+ }
err = kgdb_mem2hex((char *)addr, remcom_out_buffer, length);
if (!err)
error_packet(remcom_out_buffer, -EINVAL);
--
2.50.1 (Apple Git-155)