* 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox