Fix a buffer overflow

This commit is contained in:
Palmer Dabbelt 2017-04-13 18:52:11 -07:00
parent 98df29b8d1
commit 22d102e3c1
4 changed files with 36 additions and 12 deletions

View File

@ -15,11 +15,11 @@ riscv_addr_t riscv_program_gal(struct riscv_program *p, riscv_addr_t addr);
int riscv_program_lah(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_lal(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_insert(struct riscv_program *p, riscv_insn_t i);
/* Program interface. */
int riscv_program_init(struct riscv_program *p, struct target *target)
{
LOG_DEBUG("riscv_program_init: p=0x%016lx", p);
memset(p, 0, sizeof(*p));
p->target = target;
p->instruction_count = 0;
@ -59,11 +59,17 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
if (p->writes_memory && (riscv_program_fence(p) != ERROR_OK)) {
LOG_ERROR("Unable to write fence");
for(size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
LOG_ERROR("ram[%02x]: DASM(0x%08lx) [0x%08lx]", i, p->debug_buffer[i], p->debug_buffer[i]);
abort();
return ERROR_FAIL;
}
if (riscv_program_ebreak(p) != ERROR_OK) {
LOG_ERROR("Unable to write ebreak");
for(size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
LOG_ERROR("ram[%02x]: DASM(0x%08lx) [0x%08lx]", i, p->debug_buffer[i], p->debug_buffer[i]);
abort();
return ERROR_FAIL;
}
@ -145,9 +151,9 @@ riscv_insn_t riscv_program_read_ram(struct riscv_program *p, riscv_addr_t addr)
void riscv_program_write_ram(struct riscv_program *p, riscv_addr_t addr, uint64_t d)
{
if (addr < riscv_debug_buffer_addr(p->target))
return -1;
return;
if (addr > riscv_debug_buffer_addr(p->target) + (riscv_debug_buffer_size(p->target) * sizeof(p->debug_buffer[0])))
return -1;
return;
int off = (addr - riscv_debug_buffer_addr(p->target)) / sizeof(p->debug_buffer[0]);
p->debug_buffer[off] = d;
@ -329,12 +335,14 @@ int riscv_program_dont_restore_register(struct riscv_program *p, enum gdb_regno
{
assert(r < RISCV_REGISTER_COUNT);
p->writes_xreg[r] = 0;
return ERROR_OK;
}
int riscv_program_do_restore_register(struct riscv_program *p, enum gdb_regno r)
{
assert(r < RISCV_REGISTER_COUNT);
p->writes_xreg[r] = 1;
return ERROR_OK;
}
void riscv_program_reserve_register(struct riscv_program *p, enum gdb_regno r)
@ -393,10 +401,18 @@ int riscv_program_lal(struct riscv_program *p, enum gdb_regno d, riscv_addr_t ad
int riscv_program_insert(struct riscv_program *p, riscv_insn_t i)
{
if (p->instruction_count + p->data_count + 1 > riscv_debug_buffer_size(p->target))
LOG_DEBUG("instruction_count: %d (p=0x%016lx)", p->instruction_count, p);
if (p->instruction_count + p->data_count + 1 > riscv_debug_buffer_size(p->target)) {
LOG_DEBUG("Unable to insert instruction:");
LOG_DEBUG(" instruction_count=%d", p->instruction_count);
LOG_DEBUG(" data_count =%d", p->data_count);
LOG_DEBUG(" buffer size =%d", riscv_debug_buffer_size(p->target));
return ERROR_FAIL;
}
LOG_DEBUG("PROGBUF[%d] = DASM(0x%08x) [0x%08x]", p->instruction_count, i, i);
p->debug_buffer[p->instruction_count] = i;
p->instruction_count++;
return ERROR_OK;
}

View File

@ -3,7 +3,7 @@
#include "riscv.h"
#define RISCV_MAX_DEBUG_BUFFER_SIZE 16
#define RISCV_MAX_DEBUG_BUFFER_SIZE 32
#define RISCV_REGISTER_COUNT 32
#define RISCV_DSCRATCH_COUNT 2

View File

@ -569,6 +569,10 @@ static int register_write_direct(struct target *target, unsigned number,
riscv_program_write_ram(&program, input + 4, value >> 32);
case 32:
riscv_program_write_ram(&program, input, value);
break;
default:
LOG_ERROR("Unknown XLEN: %d\n", riscv_xlen(target));
abort();
}
if (number >= GDB_REGNO_XPR0 && number <= GDB_REGNO_XPR31) {
@ -1132,6 +1136,9 @@ static int examine(struct target *target)
* program buffer. */
r->debug_buffer_size[i] = riscv013_progbuf_size(target);
/* Guess this is a 32-bit system, we're probing it. */
r->xlen[i] = 32;
/* First find the low 32 bits of the program buffer. This is
* used to check for alignment. */
struct riscv_program program32;
@ -1149,7 +1156,6 @@ static int examine(struct target *target)
r->xlen[i] = -1;
continue;
}
r->xlen[i] = 32;
r->debug_buffer_addr[i] = progbuf_addr;
/* Check to see if the core can execute 64 bit instructions.

View File

@ -767,10 +767,7 @@ void riscv_info_init(riscv_info_t *r)
r->rtos_enabled = true;
for (size_t h = 0; h < RISCV_MAX_HARTS; ++h) {
/* FIXME: I need to rip out Tim's probing sequence, as it
* disrupts the running code. For now, I'm just hard-coding
* XLEN to 64 for all cores at reset. */
r->xlen[h] = 64;
r->xlen[h] = -1;
r->hart_state[h] = RISCV_HART_UNKNOWN;
r->debug_buffer_addr[h] = -1;
@ -904,11 +901,16 @@ bool riscv_rtos_enabled(const struct target *target)
void riscv_set_current_hartid(struct target *target, int hartid)
{
RISCV_INFO(r);
register_cache_invalidate(target->reg_cache);
r->current_hartid = hartid;
r->select_current_hart(target);
/* This might get called during init, in which case we shouldn't be
* setting up the register cache. */
if (!target_was_examined(target))
return;
/* Update the register list's widths. */
register_cache_invalidate(target->reg_cache);
for (size_t i = 0; i < GDB_REGNO_COUNT; ++i) {
struct reg *reg = &target->reg_cache->reg_list[i];