mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
kgdb patches for 7.4
Varied updates this cycle. Naveen Kumar Chaudhary fixed a memory leak when the environment is already full, eliminated to weird historical cruft (CMD_BUFLEN having different values in different files) and removed some dead code. Fang Xieyan tackled a family of related buffer overflows in the gdb remote protocol parsing (great fixes from a defensive coding point of view but not security relavent; gdb can already do anything it wants to). Signed-off-by: Daniel Thompson (RISCstar) <danielt@kernel.org> -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEELzVBU1D3lWq6cKzwfOMlXTn3iKEFAmriKxkACgkQfOMlXTn3 iKH/JRAAkKvioKgkDhKL87baXMkupx5sYusMxd+x9b7nI4Ar/ml+IR4IL1kjIR8k A5uOQnTeXQOSa8X7oii0w0eiZ2A7cy9B05CQUt4Iy7oI+auMMaCEfmX6MxIvGWRK Jytl2XqqyIViEMuVPhd4VDktBbl5CPP3302H9qzI9INIlXExBqtp75KyCQ5o8Qfb CG7mowIw4bVz3tLF0mGpm2TZOq6CIbulUHap6HIiTFIkpoz6jIvXYpYxarGZywlW C8JnFXBtoiZ5917br/TSu5rql3ZbMEBH7h8Ssymx33/9O752i/842TSwEQQ1+fcE FBVXSLb8LS+9rWabGoVpeRS+/IaJnGCtVyNj01a32nDBpzFowyZuOyuTFYH9EwX1 62N4LbsttoYFoLSUOztM1bdKdgVE4qQEL462TwX93GeQTjWgGsQKJt7KH6S1XUa4 JNgG7YM6tnMa4McUGWZ/x84uu5xhChZJvyKb7pnBUjL6LqIy+p9SoWvxW2U8TdQb 74qshJxhVLVJDCkKTOsUwfqQcmM2l8ipVNVu3za9/aVtCfUjkzjFcJVSJBnVgTkM jbJubv+tUqXr3OiwJiIArSYut9MdMiXpDjT6bcUPezs+uIPnRw+QHBXo32+Xb+2e 3ulIoN0xbTPijsCzLaC01f5Jcynjlhg6n55AQMhD+zl9stK5t9g= =VUlE -----END PGP SIGNATURE----- Merge tag 'kgdb-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/danielt/linux Pull kgdb updates from Daniel Thompson: "Varied updates this cycle. Naveen Kumar Chaudhary fixed a memory leak when the environment is already full, eliminated to weird historical cruft (CMD_BUFLEN having different values in different files) and removed some dead code. Fang Xieyan tackled a family of related buffer overflows in the gdb remote protocol parsing (great fixes from a defensive coding point of view but not security relavent; gdb can already do anything it wants to)" * tag 'kgdb-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/danielt/linux: kgdb: Fix buffer overflow in the qRcmd packet handler kgdb: Fix buffer overflow in the 'M' and 'X' packet handlers kgdb: Fix buffer overflow in the 'm' packet handler kgdb: remove unreachable return in kgdb_reenter_check() kdb: unify CMD_BUFLEN definition into kdb_private.h kdb: fix memory leak in kdb_setenv() when environment is full
This commit is contained in:
commit
5fade975d5
|
|
@ -555,8 +555,6 @@ static int kgdb_reenter_check(struct kgdb_state *ks)
|
|||
#endif
|
||||
dump_stack();
|
||||
panic("Recursive entry to debugger");
|
||||
|
||||
return 1;
|
||||
}
|
||||
NOKPROBE_SYMBOL(kgdb_reenter_check);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -563,6 +594,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);
|
||||
|
|
@ -778,9 +817,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);
|
||||
|
|
@ -985,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 */
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
#include <linux/kallsyms.h>
|
||||
#include "kdb_private.h"
|
||||
|
||||
#define CMD_BUFLEN 256
|
||||
char kdb_prompt_str[CMD_BUFLEN];
|
||||
|
||||
int kdb_trap_printk;
|
||||
|
|
|
|||
|
|
@ -338,6 +338,7 @@ static int kdb_setenv(const char *var, const char *val)
|
|||
}
|
||||
}
|
||||
|
||||
kfree(ep);
|
||||
return KDB_ENVFULL;
|
||||
}
|
||||
|
||||
|
|
@ -783,8 +784,6 @@ static int kdb_exec_defcmd(int argc, const char **argv)
|
|||
|
||||
/* Command history */
|
||||
#define KDB_CMD_HISTORY_COUNT 32
|
||||
#define CMD_BUFLEN 200 /* kdb_printf: max printline
|
||||
* size == 256 */
|
||||
static unsigned int cmd_head, cmd_tail;
|
||||
static unsigned int cmdptr;
|
||||
static char cmd_hist[KDB_CMD_HISTORY_COUNT][CMD_BUFLEN];
|
||||
|
|
@ -1265,8 +1264,8 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
|
|||
|
||||
do_full_getstr:
|
||||
/* PROMPT can only be set if we have MEM_READ permission. */
|
||||
snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"),
|
||||
raw_smp_processor_id());
|
||||
snprintf(kdb_prompt_str, CMD_BUFLEN,
|
||||
kdbgetenv("PROMPT"), raw_smp_processor_id());
|
||||
|
||||
/*
|
||||
* Fetch command from keyboard
|
||||
|
|
|
|||
|
|
@ -225,7 +225,8 @@ extern void kdb_kbd_cleanup_state(void);
|
|||
#define kdb_kbd_cleanup_state()
|
||||
#endif /* ! CONFIG_KDB_KEYBOARD */
|
||||
|
||||
extern char kdb_prompt_str[];
|
||||
#define CMD_BUFLEN 256
|
||||
extern char kdb_prompt_str[CMD_BUFLEN];
|
||||
|
||||
#define KDB_WORD_SIZE ((int)sizeof(unsigned long))
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user