diff options
| author | Fang Xieyan <fangxy@xiaopeng.com> | 2026-09-15 02:03:44 +0800 |
|---|---|---|
| committer | Daniel Thompson <daniel@riscstar.com> | 2026-10-28 16:55:40 +0000 |
| commit | ac0159129e2cb99a70c4b80cfbf58d03e092dc7b (patch) | |
| tree | 2dd0e001cce129578973f293340ea0383c596c7e /kernel | |
| parent | 1865f1ea3b54bde68da5a68f0f56fbc1ebf69fbf (diff) | |
kgdb: Fix buffer overflow in the 'm' packet handler
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@vger.kernel.org
Assisted-by: Hawkeye:GLM-5.3-flash
Assisted-by: Qoder:Qwen3.8-Max
Signed-off-by: Fang Xieyan <fangxy@xiaopeng.com>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Link: https://lore.kernel.org/r/20260914180344.15485-1-fangxy@xiaopeng.com
Signed-off-by: Daniel Thompson <daniel@riscstar.com>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/debug/gdbstub.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c index e271a436d60e..5774292c93ae 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); |
