From 07f683dc41bb3378e55224a02cad59fff83e84aa Mon Sep 17 00:00:00 2001 From: vhaudiquet Date: Mon, 23 Oct 2023 17:52:09 +0200 Subject: [PATCH] Hardened memory bounds check --- src/memory/memory.c | 81 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 16 deletions(-) diff --git a/src/memory/memory.c b/src/memory/memory.c index ee5b626..4c3109e 100644 --- a/src/memory/memory.c +++ b/src/memory/memory.c @@ -50,7 +50,7 @@ void mem_write8(uint32_t address, uint8_t value) { if(io->reg_size == 1) { - void (*fn_write)(uint32_t, uint8_t) = io->fn_write; + void (*fn_write)(uint32_t, uint8_t) = io->fn_write; fn_write(address, value); return; } @@ -63,6 +63,13 @@ void mem_write8(uint32_t address, uint8_t value) io = io->next; } + // Check if we are inside of physical memory + if(address + 1 > memory_size) + { + fprintf(stderr, "MEMORY: Invalid write of size 1 outside of physical memory at address 0x%x\n", address); + exit(EXIT_FAILURE); + } + // Proceed with memory write pthread_mutex_lock(&memory_mutex); memory[address] = value; @@ -81,7 +88,7 @@ void mem_write16(uint32_t address, uint16_t value) { if(io->reg_size == 2) { - void (*fn_write)(uint32_t, uint16_t) = io->fn_write; + void (*fn_write)(uint32_t, uint16_t) = io->fn_write; fn_write(address, value); return; } @@ -94,6 +101,13 @@ void mem_write16(uint32_t address, uint16_t value) io = io->next; } + // Check if we are inside of physical memory + if(address + 2 > memory_size) + { + fprintf(stderr, "MEMORY: Invalid write of size 2 outside of physical memory at address 0x%x\n", address); + exit(EXIT_FAILURE); + } + // Proceed with memory write pthread_mutex_lock(&memory_mutex); *((uint16_t*) &memory[address]) = value; @@ -112,7 +126,7 @@ void mem_write32(uint32_t address, uint32_t value) { if(io->reg_size == 4) { - void (*fn_write)(uint32_t, uint32_t) = io->fn_write; + void (*fn_write)(uint32_t, uint32_t) = io->fn_write; fn_write(address, value); return; } @@ -125,6 +139,13 @@ void mem_write32(uint32_t address, uint32_t value) io = io->next; } + // Check if we are inside of physical memory + if(address + 4 > memory_size) + { + fprintf(stderr, "MEMORY: Invalid write of size 1 outside of physical memory at address 0x%x\n", address); + exit(EXIT_FAILURE); + } + // Proceed with memory write pthread_mutex_lock(&memory_mutex); *((uint32_t*) &memory[address]) = value; @@ -135,7 +156,7 @@ uint8_t mem_read8(uint32_t address) { address = mmu_resolve(cpu0, READ, address); - // Look wether we are on an MMIO region + // Look wether we are on an MMIO region struct MMIO_ENTRY* io = mmio; while(io) { @@ -143,7 +164,7 @@ uint8_t mem_read8(uint32_t address) { if(io->reg_size == 1) { - uint8_t (*fn_read)(uint32_t) = io->fn_read; + uint8_t (*fn_read)(uint32_t) = io->fn_read; return fn_read(address); } else @@ -155,18 +176,25 @@ uint8_t mem_read8(uint32_t address) io = io->next; } + // Check if we are inside of physical memory + if(address + 1 > memory_size) + { + fprintf(stderr, "MEMORY: Invalid read of size 1 outside of physical memory at address 0x%x\n", address); + exit(EXIT_FAILURE); + } + // Proceed with memory read pthread_mutex_lock(&memory_mutex); uint8_t tr = memory[address]; pthread_mutex_unlock(&memory_mutex); - return tr; + return tr; } uint16_t mem_read16(uint32_t address) { address = mmu_resolve(cpu0, READ, address); - // Look wether we are on an MMIO region + // Look wether we are on an MMIO region struct MMIO_ENTRY* io = mmio; while(io) { @@ -174,7 +202,7 @@ uint16_t mem_read16(uint32_t address) { if(io->reg_size == 2) { - uint16_t (*fn_read)(uint32_t) = io->fn_read; + uint16_t (*fn_read)(uint32_t) = io->fn_read; return fn_read(address); } else @@ -186,18 +214,25 @@ uint16_t mem_read16(uint32_t address) io = io->next; } + // Check if we are inside of physical memory + if(address + 2 > memory_size) + { + fprintf(stderr, "MEMORY: Invalid read of size 2 outside of physical memory at address 0x%x\n", address); + exit(EXIT_FAILURE); + } + // Proceed with memory read pthread_mutex_lock(&memory_mutex); uint16_t tr = *((uint16_t*) &memory[address]); pthread_mutex_unlock(&memory_mutex); - return tr; + return tr; } uint32_t mem_read32(uint32_t address) { address = mmu_resolve(cpu0, READ, address); - - // Look wether we are on an MMIO region + + // Look wether we are on an MMIO region struct MMIO_ENTRY* io = mmio; while(io) { @@ -205,7 +240,7 @@ uint32_t mem_read32(uint32_t address) { if(io->reg_size == 4) { - uint32_t (*fn_read)(uint32_t) = io->fn_read; + uint32_t (*fn_read)(uint32_t) = io->fn_read; return fn_read(address); } else @@ -217,18 +252,25 @@ uint32_t mem_read32(uint32_t address) io = io->next; } + // Check if we are inside of physical memory + if(address + 4 > memory_size) + { + fprintf(stderr, "MEMORY: Invalid read of size 4 outside of physical memory at address 0x%x\n", address); + exit(EXIT_FAILURE); + } + // Proceed with memory read pthread_mutex_lock(&memory_mutex); uint32_t tr = *((uint32_t*) &memory[address]); pthread_mutex_unlock(&memory_mutex); - return tr; + return tr; } uint32_t mem_fetch(uint32_t address) { address = mmu_resolve(cpu0, INSTRUCTION_FETCH, address); - - // Look wether we are on an MMIO region + + // Look wether we are on an MMIO region struct MMIO_ENTRY* io = mmio; while(io) { @@ -240,9 +282,16 @@ uint32_t mem_fetch(uint32_t address) io = io->next; } + // Check if we are inside of physical memory + if(address + 4 > memory_size) + { + fprintf(stderr, "MEMORY: Invalid fetch outside of physical memory at address 0x%x\n", address); + exit(EXIT_FAILURE); + } + // Proceed with memory read pthread_mutex_lock(&memory_mutex); uint32_t tr = *((uint32_t*) &memory[address]); pthread_mutex_unlock(&memory_mutex); - return tr; + return tr; }