Disable stack canary by default

This commit is contained in:
Toby Jaffey 2025-12-12 21:01:40 +00:00
parent 3ecd16c8bf
commit 789cd74516
4 changed files with 13 additions and 3 deletions

View file

@ -183,6 +183,8 @@ The uvm32 memory size is set at compile time with `-DUVM32_MEMORY_SIZE=X` (in by
Define `UVM32_ERROR_STRINGS` to add an `errstr` field to `uvm32_evt_err_t` giving a printable error string. Define `UVM32_ERROR_STRINGS` to add an `errstr` field to `uvm32_evt_err_t` giving a printable error string.
Define `UVM32_STACK_PROTECTION` to enable a basic stack canary, to cause an early crash when the stack grows too large. Without this, the VM will normally crash (safely) in some other way which is less easily detected.
## Debugging ## Debugging
Binaries can be disassembled with Binaries can be disassembled with

Binary file not shown.

View file

@ -16,8 +16,9 @@
// On an invalid operation, an error is set in uvm32_state_t, but a valid pointer still needs to be temporarily used // On an invalid operation, an error is set in uvm32_state_t, but a valid pointer still needs to be temporarily used
static uint32_t garbage; static uint32_t garbage;
// magic value for stack canary #ifdef UVM32_STACK_PROTECTION
#define STACK_CANARY_VALUE 0x42 #define STACK_CANARY_VALUE 0x42 // magic value for stack canary
#endif
#ifndef UVM32_MEMCPY #ifndef UVM32_MEMCPY
#define UVM32_MEMCPY uvm32_memcpy #define UVM32_MEMCPY uvm32_memcpy
@ -101,8 +102,9 @@ bool uvm32_load(uvm32_state_t *vmst, const uint8_t *rom, int len) {
} }
UVM32_MEMCPY(vmst->_memory, rom, len); UVM32_MEMCPY(vmst->_memory, rom, len);
#ifdef UVM32_STACK_PROTECTION
vmst->_stack_canary = (uint8_t *)NULL; vmst->_stack_canary = (uint8_t *)NULL;
#endif
return true; return true;
} }
@ -207,11 +209,13 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter)
orig_instr_meter = min_instrs; orig_instr_meter = min_instrs;
} }
#ifdef UVM32_STACK_PROTECTION
if (vmst->_stack_canary != NULL && *vmst->_stack_canary != STACK_CANARY_VALUE) { if (vmst->_stack_canary != NULL && *vmst->_stack_canary != STACK_CANARY_VALUE) {
setStatusErr(vmst, UVM32_ERR_INTERNAL_CORE); setStatusErr(vmst, UVM32_ERR_INTERNAL_CORE);
setup_err_evt(vmst, evt); setup_err_evt(vmst, evt);
return orig_instr_meter - instr_meter; return orig_instr_meter - instr_meter;
} }
#endif
if (vmst->_status != UVM32_STATUS_PAUSED) { if (vmst->_status != UVM32_STATUS_PAUSED) {
setStatusErr(vmst, UVM32_ERR_NOTREADY); setStatusErr(vmst, UVM32_ERR_NOTREADY);
@ -243,6 +247,7 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter)
setStatus(vmst, UVM32_STATUS_ENDED); setStatus(vmst, UVM32_STATUS_ENDED);
break; break;
case UVM32_SYSCALL_STACKPROTECT: { case UVM32_SYSCALL_STACKPROTECT: {
#ifdef UVM32_STACK_PROTECTION
// don't allow errant code to change it once set // don't allow errant code to change it once set
if (vmst->_stack_canary == (uint8_t *)NULL) { if (vmst->_stack_canary == (uint8_t *)NULL) {
uint32_t param0 = vmst->_core.regs[10]; // a0 uint32_t param0 = vmst->_core.regs[10]; // a0
@ -263,6 +268,7 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter)
*vmst->_stack_canary = STACK_CANARY_VALUE; *vmst->_stack_canary = STACK_CANARY_VALUE;
} }
} }
#endif
} break; } break;
default: default:
// user defined syscalls // user defined syscalls

View file

@ -118,7 +118,9 @@ typedef struct {
struct MiniRV32IMAState _core; /*! CPU registers */ struct MiniRV32IMAState _core; /*! CPU registers */
uint8_t _memory[UVM32_MEMORY_SIZE]; /*! Memory */ uint8_t _memory[UVM32_MEMORY_SIZE]; /*! Memory */
uvm32_evt_t _ioevt; /*! Event to be returned on next pause */ uvm32_evt_t _ioevt; /*! Event to be returned on next pause */
#ifdef UVM32_STACK_PROTECTION
uint8_t *_stack_canary; /*! Location of stack canary */ uint8_t *_stack_canary; /*! Location of stack canary */
#endif
uint8_t *_extram; /*! External RAM pointer, or NULL */ uint8_t *_extram; /*! External RAM pointer, or NULL */
uint32_t _extramLen; /*! Length of external RAM */ uint32_t _extramLen; /*! Length of external RAM */
bool _extramDirty; /*! Flag to indicate VM code has modified extram since last run */ bool _extramDirty; /*! Flag to indicate VM code has modified extram since last run */