Fixed multiple buffer overflow vulnerabilities leading to ACE in code handling DMAs

This commit is contained in:
Matt Pharoah 2024-06-10 16:14:08 -04:00
parent 1b57f9199b
commit baba05c542
8 changed files with 97 additions and 25 deletions

View File

@ -26,6 +26,7 @@
#include "../api/callbacks.h"
#include "../memory/memory.h"
#include "../ri/ri_controller.h"
#include "../ri/safe_rdram.h"
#include <string.h>
@ -70,14 +71,21 @@ static void flashram_command(struct pi_controller *pi, uint32_t command)
case FLASHRAM_MODE_ERASE:
{
for (i=flashram->erase_offset; i<(flashram->erase_offset+128); ++i)
flashram->data[i^S8] = 0xff;
{
if ((i^S8) < (unsigned)FLASHRAM_SIZE)
flashram->data[i^S8] = 0xff;
}
flashram_save(flashram);
}
break;
case FLASHRAM_MODE_WRITE:
{
for(i = 0; i < 128; ++i)
flashram->data[(flashram->erase_offset+i)^S8]= dram[(flashram->write_pointer+i)^S8];
{
const unsigned int flash_i = (flashram->erase_offset+i)^S8;
if (flash_i >= (unsigned)FLASHRAM_SIZE) continue;
flashram->data[flash_i] = rdram_safe_read_byte(dram, (flashram->write_pointer+i)^S8);
}
flashram_save(flashram);
}
break;
@ -169,7 +177,10 @@ void dma_read_flashram(struct pi_controller *pi)
cart_addr = ((pi->regs[PI_CART_ADDR_REG]-0x08000000)&0xffff)*2;
for (i = 0; i < length; ++i)
((uint8_t*)dram)[(dram_addr+i)^S8] = mem[(cart_addr+i)^S8];
{
const unsigned int cart_i = (cart_addr+i)^S8;
rdram_safe_write_byte(dram, (dram_addr+i)^S8, (cart_i < (unsigned)FLASHRAM_SIZE) ? mem[cart_i] : 0);
}
break;
default:
DebugMessage(M64MSG_WARNING, "unknown dma_read_flashram: %x", flashram->mode);

View File

@ -32,10 +32,13 @@
#include "../r4300/r4300_core.h"
#include "../ri/rdram_detection_hack.h"
#include "../ri/ri_controller.h"
#include "../ri/safe_rdram.h"
#include "../dd/dd_controller.h"
#include <string.h>
extern int g_rom_size;
enum
{
/* PI_STATUS - read */
@ -87,7 +90,11 @@ static void dma_pi_read(struct pi_controller *pi)
dram = (uint8_t*)pi->ri->rdram.dram;
for (i = 0; i < length; ++i)
rom[(rom_address + i) ^ S8] = dram[(dram_address + i) ^ S8];
{
const unsigned int rom_i = (rom_address + i) ^ S8;
if (rom_i >= (uint32_t)g_rom_size) continue;
rom[rom_i] = rdram_safe_read_byte(dram, (dram_address + i) ^ S8);
}
}
else if (pi->regs[PI_CART_ADDR_REG] >= 0x08000000
&& pi->regs[PI_CART_ADDR_REG] < 0x08010000)
@ -181,7 +188,10 @@ static void dma_pi_write(struct pi_controller *pi)
dram = (uint8_t*)pi->ri->rdram.dram;
for (i = 0; i < length; ++i)
dram[(dram_address + i) ^ S8] = rom[(rom_address + i) ^ S8];
{
const unsigned int rom_i = (rom_address + i) ^ S8;
rdram_safe_write_byte(dram, (dram_address + i) ^ S8, (rom_i < (uint32_t)g_rom_size) ? rom[rom_i] : 0u);
}
invalidate_r4300_cached_code(0x80000000 + dram_address, length);
invalidate_r4300_cached_code(0xa0000000 + dram_address, length);
@ -274,8 +284,10 @@ static void dma_pi_write(struct pi_controller *pi)
rom = pi->cart_rom.rom;
}
for (i = 0; i < length; ++i)
dram[(dram_address + i) ^ S8] = rom[(rom_address + i) ^ S8];
for (i = 0; i < length; ++i) {
const unsigned int rom_i = (rom_address + i) ^ S8;
rdram_safe_write_byte(dram, (dram_address + i) ^ S8, (rom_i < (uint32_t)g_rom_size) ? rom[rom_i] : 0);
}
invalidate_r4300_cached_code(0x80000000 + dram_address, length);
invalidate_r4300_cached_code(0xa0000000 + dram_address, length);

View File

@ -25,6 +25,7 @@
#include "memory/memory.h"
#include "ri/ri_controller.h"
#include "ri/safe_rdram.h"
#include <stddef.h>
#include <stdint.h>
@ -58,7 +59,11 @@ void dma_write_sram(struct pi_controller* pi)
uint32_t dram_addr = pi->regs[PI_DRAM_ADDR_REG];
for(i = 0; i < length; ++i)
sram[(cart_addr+i)^S8] = dram[(dram_addr+i)^S8];
{
const unsigned int sram_i = (cart_addr+i)^S8;
if (sram_i >= (unsigned)SRAM_SIZE) continue;
sram[sram_i] = rdram_safe_read_byte(dram, (dram_addr+i)^S8);
}
sram_save(&pi->sram);
}
@ -74,5 +79,8 @@ void dma_read_sram(struct pi_controller* pi)
uint32_t dram_addr = pi->regs[PI_DRAM_ADDR_REG];
for(i = 0; i < length; ++i)
dram[(dram_addr+i)^S8] = sram[(cart_addr+i)^S8];
{
const unsigned int sram_i = (cart_addr+i)^S8;
rdram_safe_write_byte(dram, (dram_addr+i)^S8, (sram_i < (unsigned)SRAM_SIZE) ? sram[sram_i] : 0);
}
}

View File

@ -23,6 +23,7 @@
#include "ri_controller.h"
#include "../memory/memory.h"
#include "./safe_rdram.h"
#include <string.h>
@ -65,19 +66,13 @@ int write_rdram_regs(void* opaque, uint32_t address, uint32_t value, uint32_t ma
int read_rdram_dram(void* opaque, uint32_t address, uint32_t* value)
{
struct ri_controller* ri = (struct ri_controller*)opaque;
uint32_t addr = RDRAM_DRAM_ADDR(address);
*value = ri->rdram.dram[addr];
*value = rdram_safe_read_word(ri->rdram.dram, address);
return 0;
}
int write_rdram_dram(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
{
struct ri_controller* ri = (struct ri_controller*)opaque;
uint32_t addr = RDRAM_DRAM_ADDR(address);
ri->rdram.dram[addr] = MASKED_WRITE(&ri->rdram.dram[addr], value, mask);
rdram_safe_masked_write_word(ri->rdram.dram, address, value, mask);
return 0;
}

View File

@ -29,10 +29,6 @@
#define RDRAM_REG(a) ((a & 0x3ff) >> 2)
#endif
#ifndef RDRAM_DRAM_ADDR
#define RDRAM_DRAM_ADDR(a) ((address & 0xffffff) >> 2)
#endif
enum rdram_registers
{
RDRAM_CONFIG_REG,

View File

@ -0,0 +1,40 @@
#ifndef M64P_RI_SAFE_RDRAM_H
#define M64P_RI_SAFE_RDRAM_H
#include <stdint.h>
inline uint8_t rdram_safe_read_byte(const void *rdram, uint32_t addr)
{
addr &= 0x3ffffffu;
return (addr < 0x800000u) ? ((const uint8_t*)rdram)[addr] : 0;
}
inline void rdram_safe_write_byte(void *rdram, uint32_t addr, uint8_t value)
{
addr &= 0x3ffffffu;
if (addr < 0x800000u)
((uint8_t*)rdram)[addr] = value;
}
inline uint32_t rdram_safe_read_word(const void *rdram, uint32_t addr)
{
addr = (addr & 0x3ffffffu) >> 2;
return (addr < 0x200000u) ? ((const uint32_t*)rdram)[addr] : 0u;
}
inline void rdram_safe_write_word(void *rdram, uint32_t addr, uint32_t value)
{
addr = (addr & 0x3ffffffu) >> 2;
if (addr < 0x200000u)
((uint32_t*)rdram)[addr] = value;
}
inline void rdram_safe_masked_write_word(void *rdram, uint32_t addr, uint32_t value, uint32_t mask)
{
addr = (addr & 0x3ffffffu) >> 2;
if (addr >= 0x200000u) return;
uint32_t *word = &((uint32_t*)rdram)[addr];
*word = (*word & ~mask) | (value & mask);
}
#endif

View File

@ -29,6 +29,7 @@
#include "r4300/r4300_core.h"
#include "../rdp/rdp_core.h"
#include "../ri/ri_controller.h"
#include "../ri/safe_rdram.h"
#include <stdio.h>
#include <string.h>
@ -46,7 +47,7 @@ static void dma_sp_write(struct rsp_core* sp, unsigned length, unsigned count, u
{
for(i = 0; i < length; i++)
{
spmem[memaddr^S8] = dram[dramaddr^S8];
spmem[(memaddr^S8) & 0xfffu] = rdram_safe_read_byte(dram, dramaddr^S8);
memaddr++;
dramaddr++;
}
@ -67,7 +68,7 @@ static void dma_sp_read(struct rsp_core* sp, unsigned length, unsigned count, un
{
for(i = 0; i < length; i++)
{
dram[dramaddr^S8] = spmem[memaddr^S8];
rdram_safe_write_byte(dram, dramaddr^S8, spmem[(memaddr^S8) & 0xfffu]);
memaddr++;
dramaddr++;
}

View File

@ -28,6 +28,7 @@
#include "../memory/memory.h"
#include "../r4300/r4300_core.h"
#include "../ri/ri_controller.h"
#include "../ri/safe_rdram.h"
#include <string.h>
@ -51,7 +52,11 @@ static void dma_si_write(struct si_controller* si)
}
for (i = 0; i < PIF_RAM_SIZE; i += 4)
*((uint32_t*)(&si->pif.ram[i])) = sl(si->ri->rdram.dram[(si->regs[SI_DRAM_ADDR_REG]+i)/4]);
{
const uint32_t dram_i = si->regs[SI_DRAM_ADDR_REG]+i;
const uint32_t value = rdram_safe_read_word(si->ri->rdram.dram, dram_i);
*((uint32_t*)(&si->pif.ram[i])) = sl(value);
}
update_pif_write(si);
cp0_update_count();
@ -81,7 +86,11 @@ static void dma_si_read(struct si_controller* si)
update_pif_read(si);
for (i = 0; i < PIF_RAM_SIZE; i += 4)
si->ri->rdram.dram[(si->regs[SI_DRAM_ADDR_REG]+i)/4] = sl(*(uint32_t*)(&si->pif.ram[i]));
{
const uint32_t dram_i = si->regs[SI_DRAM_ADDR_REG]+i;
const uint32_t value = *(uint32_t*)(&si->pif.ram[i]);
rdram_safe_write_word(si->ri->rdram.dram, dram_i, sl(value));
}
cp0_update_count();
if (g_delay_si)