mirror of
https://github.com/libretro/parallel-n64.git
synced 2024-11-27 02:10:56 +00:00
Merge pull request #776 from mpharoah/mpharoah/security/fix-ace-exploit
[Security] Fixed multiple buffer overflow vulnerabilities leading to arbitrary code execution
This commit is contained in:
commit
330fa5efd3
@ -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)
|
||||
{
|
||||
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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
40
mupen64plus-core/src/ri/safe_rdram.h
Normal file
40
mupen64plus-core/src/ri/safe_rdram.h
Normal 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
|
@ -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++;
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user