* FAILED: patch "[PATCH] kgdb: Fix buffer overflow in the 'M' and 'X' packet handlers" failed to apply to 5.10-stable tree
@ 2026-11-07 11:30 Sasha Levin
2026-11-11 19:35 ` [PATCH 5.10.y 1/2] kernel: debug: Ordinary typo fixes in the file gdbstub.c Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: Sasha Levin @ 2026-11-07 11:30 UTC (permalink / raw)
To: fangxy, daniel; +Cc: stable
The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 13962ef7021ef2531a4f6650eca87c363e6c9c32
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '20261107063025-failed-5.10-13962ef7021e@kernel.org' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 13962ef7021ef2531a4f6650eca87c363e6c9c32 Mon Sep 17 00:00:00 2001
From: Fang Xieyan <fangxy@xiaopeng.com>
Date: Tue, 22 Sep 2026 23:49:07 +0800
Subject: [PATCH] kgdb: Fix buffer overflow in the 'M' and 'X' packet handlers
write_mem_msg() passes the length claimed by an 'M' or 'X' packet directly
to kgdb_hex2mem() or kgdb_ebin2mem(). A malformed packet can claim more
data than was actually received, causing the decoders to read past
remcom_in_buffer.
Record the received payload length in get_packet() and use it to bound
the decoders. 'M' carries two hex characters per byte, while 'X' carries
one byte per output byte except that a 0x7d escape consumes an additional
input byte. Pass the packet end to kgdb_ebin2mem() so both reads are
checked against the received data.
Keep zero-length 'X' packets valid, as GDB uses them to probe binary
download support.
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>
Link: https://lore.kernel.org/r/20260922154907.90535-1-fangxy@xiaopeng.com
Signed-off-by: Daniel Thompson <daniel@riscstar.com>
---
kernel/debug/gdbstub.c | 45 +++++++++++++++++++++++++++++++++++-------
1 file changed, 38 insertions(+), 7 deletions(-)
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c
index 5774292c93aec..4102e2e68d806 100644
--- a/kernel/debug/gdbstub.c
+++ b/kernel/debug/gdbstub.c
@@ -43,6 +43,8 @@
/* Our I/O buffers. */
static char remcom_in_buffer[BUFMAX];
static char remcom_out_buffer[BUFMAX];
+/* Payload bytes get_packet() stored in remcom_in_buffer, excluding the NUL. */
+static int remcom_in_len;
static int gdbstub_use_prev_in_buf;
static int gdbstub_prev_in_buf_pos;
@@ -87,7 +89,7 @@ static int gdbstub_read_wait(void)
}
#endif
/* scan for the sequence $<data>#<checksum> */
-static void get_packet(char *buffer)
+static int get_packet(char *buffer)
{
unsigned char checksum;
unsigned char xmitcsum;
@@ -135,6 +137,8 @@ static void get_packet(char *buffer)
}
buffer[count] = 0;
} while (checksum != xmitcsum);
+
+ return count;
}
/*
@@ -321,16 +325,26 @@ int kgdb_hex2long(char **ptr, unsigned long *long_val)
* Copy the binary array pointed to by buf into mem. Fix $, #, and
* 0x7d escaped with 0x7d. Return -EFAULT on failure or 0 on success.
* The input buf is overwritten with the result to write to mem.
+ *
+ * buf_end points one past the last byte received for this packet. Each
+ * 0x7d escape consumes a second input byte, so decoding count bytes can
+ * read up to 2 * count input bytes; stop at buf_end rather than running
+ * off the end of remcom_in_buffer.
*/
-static int kgdb_ebin2mem(char *buf, char *mem, int count)
+static int kgdb_ebin2mem(char *buf, char *mem, int count, char *buf_end)
{
int size = 0;
char *c = buf;
while (count-- > 0) {
+ if (buf >= buf_end)
+ return -EINVAL;
c[size] = *buf++;
- if (c[size] == 0x7d)
+ if (c[size] == 0x7d) {
+ if (buf >= buf_end)
+ return -EINVAL;
c[size] = *buf++ ^ 0x20;
+ }
size++;
}
@@ -367,16 +381,33 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
static int write_mem_msg(int binary)
{
char *ptr = &remcom_in_buffer[1];
+ char *buf_end = &remcom_in_buffer[remcom_in_len];
unsigned long addr;
unsigned long length;
int err;
if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' &&
kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') {
- if (binary)
- err = kgdb_ebin2mem(ptr, (char *)addr, length);
- else
+ /*
+ * Trust only the bytes actually received, not length: the
+ * client can claim more payload than it sent. 'M' decodes two
+ * hex chars per byte in place, so it needs 2 * length bytes at
+ * ptr; 'X' decodes one byte per byte, and kgdb_ebin2mem() bounds
+ * its extra 0x7d-escape reads against buf_end itself.
+ */
+ if (ptr >= buf_end)
+ return -EINVAL;
+
+ if (binary) {
+ if (length > (unsigned long)(buf_end - ptr))
+ return -EINVAL;
+ err = kgdb_ebin2mem(ptr, (char *)addr, length, buf_end);
+ } else {
+ if (length > (unsigned long)(buf_end - ptr) / 2)
+ return -EINVAL;
err = kgdb_hex2mem(ptr, (char *)addr, length);
+ }
+
if (err)
return err;
if (CACHE_FLUSH_IS_SAFE)
@@ -993,7 +1024,7 @@ int gdb_serial_stub(struct kgdb_state *ks)
/* Clear the out buffer. */
memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
- get_packet(remcom_in_buffer);
+ remcom_in_len = get_packet(remcom_in_buffer);
switch (remcom_in_buffer[0]) {
case '?': /* gdbserial status */
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 5.10.y 1/2] kernel: debug: Ordinary typo fixes in the file gdbstub.c
2026-11-07 11:30 FAILED: patch "[PATCH] kgdb: Fix buffer overflow in the 'M' and 'X' packet handlers" failed to apply to 5.10-stable tree Sasha Levin
@ 2026-11-11 19:35 ` Sasha Levin
2026-11-11 19:35 ` [PATCH 5.10.y 2/2] kgdb: Fix buffer overflow in the 'M' and 'X' packet handlers Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: Sasha Levin @ 2026-11-11 19:35 UTC (permalink / raw)
To: stable; +Cc: Bhaskar Chowdhury, Randy Dunlap, Daniel Thompson, Sasha Levin
From: Bhaskar Chowdhury <unixbhaskar@gmail.com>
[ Upstream commit 2bbd9b0f2b4ec0afa80b52b1a68bd3bc80618275 ]
s/overwitten/overwritten/
s/procesing/processing/
Signed-off-by: Bhaskar Chowdhury <unixbhaskar@gmail.com>
Link: https://lore.kernel.org/r/20210317104658.4053473-1-unixbhaskar@gmail.com
Acked-by: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Stable-dep-of: 13962ef7021e ("kgdb: Fix buffer overflow in the 'M' and 'X' packet handlers")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/debug/gdbstub.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c
index b57e5e338aab2..45f6e39d29db4 100644
--- a/kernel/debug/gdbstub.c
+++ b/kernel/debug/gdbstub.c
@@ -321,7 +321,7 @@ int kgdb_hex2long(char **ptr, unsigned long *long_val)
/*
* Copy the binary array pointed to by buf into mem. Fix $, #, and
* 0x7d escaped with 0x7d. Return -EFAULT on failure or 0 on success.
- * The input buf is overwitten with the result to write to mem.
+ * The input buf is overwritten with the result to write to mem.
*/
static int kgdb_ebin2mem(char *buf, char *mem, int count)
{
@@ -960,7 +960,7 @@ static int gdb_cmd_exception_pass(struct kgdb_state *ks)
}
/*
- * This function performs all gdbserial command procesing
+ * This function performs all gdbserial command processing
*/
int gdb_serial_stub(struct kgdb_state *ks)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 5.10.y 2/2] kgdb: Fix buffer overflow in the 'M' and 'X' packet handlers
2026-11-11 19:35 ` [PATCH 5.10.y 1/2] kernel: debug: Ordinary typo fixes in the file gdbstub.c Sasha Levin
@ 2026-11-11 19:35 ` Sasha Levin
0 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2026-11-11 19:35 UTC (permalink / raw)
To: stable; +Cc: Fang Xieyan, Daniel Thompson, Sasha Levin
From: Fang Xieyan <fangxy@xiaopeng.com>
[ Upstream commit 13962ef7021ef2531a4f6650eca87c363e6c9c32 ]
write_mem_msg() passes the length claimed by an 'M' or 'X' packet directly
to kgdb_hex2mem() or kgdb_ebin2mem(). A malformed packet can claim more
data than was actually received, causing the decoders to read past
remcom_in_buffer.
Record the received payload length in get_packet() and use it to bound
the decoders. 'M' carries two hex characters per byte, while 'X' carries
one byte per output byte except that a 0x7d escape consumes an additional
input byte. Pass the packet end to kgdb_ebin2mem() so both reads are
checked against the received data.
Keep zero-length 'X' packets valid, as GDB uses them to probe binary
download support.
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>
Link: https://lore.kernel.org/r/20260922154907.90535-1-fangxy@xiaopeng.com
Signed-off-by: Daniel Thompson <daniel@riscstar.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/debug/gdbstub.c | 45 +++++++++++++++++++++++++++++++++++-------
1 file changed, 38 insertions(+), 7 deletions(-)
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c
index 45f6e39d29db4..68a532ced844f 100644
--- a/kernel/debug/gdbstub.c
+++ b/kernel/debug/gdbstub.c
@@ -44,6 +44,8 @@
/* Our I/O buffers. */
static char remcom_in_buffer[BUFMAX];
static char remcom_out_buffer[BUFMAX];
+/* Payload bytes get_packet() stored in remcom_in_buffer, excluding the NUL. */
+static int remcom_in_len;
static int gdbstub_use_prev_in_buf;
static int gdbstub_prev_in_buf_pos;
@@ -88,7 +90,7 @@ static int gdbstub_read_wait(void)
}
#endif
/* scan for the sequence $<data>#<checksum> */
-static void get_packet(char *buffer)
+static int get_packet(char *buffer)
{
unsigned char checksum;
unsigned char xmitcsum;
@@ -136,6 +138,8 @@ static void get_packet(char *buffer)
}
buffer[count] = 0;
} while (checksum != xmitcsum);
+
+ return count;
}
/*
@@ -322,16 +326,26 @@ int kgdb_hex2long(char **ptr, unsigned long *long_val)
* Copy the binary array pointed to by buf into mem. Fix $, #, and
* 0x7d escaped with 0x7d. Return -EFAULT on failure or 0 on success.
* The input buf is overwritten with the result to write to mem.
+ *
+ * buf_end points one past the last byte received for this packet. Each
+ * 0x7d escape consumes a second input byte, so decoding count bytes can
+ * read up to 2 * count input bytes; stop at buf_end rather than running
+ * off the end of remcom_in_buffer.
*/
-static int kgdb_ebin2mem(char *buf, char *mem, int count)
+static int kgdb_ebin2mem(char *buf, char *mem, int count, char *buf_end)
{
int size = 0;
char *c = buf;
while (count-- > 0) {
+ if (buf >= buf_end)
+ return -EINVAL;
c[size] = *buf++;
- if (c[size] == 0x7d)
+ if (c[size] == 0x7d) {
+ if (buf >= buf_end)
+ return -EINVAL;
c[size] = *buf++ ^ 0x20;
+ }
size++;
}
@@ -368,16 +382,33 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
static int write_mem_msg(int binary)
{
char *ptr = &remcom_in_buffer[1];
+ char *buf_end = &remcom_in_buffer[remcom_in_len];
unsigned long addr;
unsigned long length;
int err;
if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' &&
kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') {
- if (binary)
- err = kgdb_ebin2mem(ptr, (char *)addr, length);
- else
+ /*
+ * Trust only the bytes actually received, not length: the
+ * client can claim more payload than it sent. 'M' decodes two
+ * hex chars per byte in place, so it needs 2 * length bytes at
+ * ptr; 'X' decodes one byte per byte, and kgdb_ebin2mem() bounds
+ * its extra 0x7d-escape reads against buf_end itself.
+ */
+ if (ptr >= buf_end)
+ return -EINVAL;
+
+ if (binary) {
+ if (length > (unsigned long)(buf_end - ptr))
+ return -EINVAL;
+ err = kgdb_ebin2mem(ptr, (char *)addr, length, buf_end);
+ } else {
+ if (length > (unsigned long)(buf_end - ptr) / 2)
+ return -EINVAL;
err = kgdb_hex2mem(ptr, (char *)addr, length);
+ }
+
if (err)
return err;
if (CACHE_FLUSH_IS_SAFE)
@@ -994,7 +1025,7 @@ int gdb_serial_stub(struct kgdb_state *ks)
/* Clear the out buffer. */
memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
- get_packet(remcom_in_buffer);
+ remcom_in_len = get_packet(remcom_in_buffer);
switch (remcom_in_buffer[0]) {
case '?': /* gdbserial status */
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-11-11 19:35 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 11:30 FAILED: patch "[PATCH] kgdb: Fix buffer overflow in the 'M' and 'X' packet handlers" failed to apply to 5.10-stable tree Sasha Levin
2026-11-11 19:35 ` [PATCH 5.10.y 1/2] kernel: debug: Ordinary typo fixes in the file gdbstub.c Sasha Levin
2026-11-11 19:35 ` [PATCH 5.10.y 2/2] kgdb: Fix buffer overflow in the 'M' and 'X' packet handlers Sasha Levin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.