1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-17 21:22:10 +00:00

feat(core): Introduce stack overflow detection by moving stack to the start of RAM

This commit is contained in:
tychovrahe 2022-08-09 19:16:54 +02:00 committed by TychoVrahe
parent 459270ef3f
commit 6cf92fd748
9 changed files with 58 additions and 30 deletions

View File

@ -0,0 +1 @@
Add stack overflow detection

View File

@ -0,0 +1 @@
Add stack overflow detection

View File

@ -8,7 +8,7 @@ MEMORY {
SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K
}
main_stack_base = ORIGIN(CCMRAM) + LENGTH(CCMRAM); /* 8-byte aligned full descending stack */
main_stack_base = ORIGIN(CCMRAM) + SIZEOF(.stack) ; /* 8-byte aligned full descending stack */
/* used by the startup code to populate variables used by the C code */
data_lma = LOADADDR(.data);
@ -39,6 +39,10 @@ SECTIONS {
. = ALIGN(512);
} >FLASH AT>FLASH
.stack : ALIGN(8) {
. = 16K; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
} >CCMRAM
.data : ALIGN(4) {
*(.data*);
. = ALIGN(512);
@ -54,7 +58,4 @@ SECTIONS {
. = ALIGN(4);
} >SRAM
.stack : ALIGN(8) {
. = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */
} >CCMRAM
}

View File

@ -129,7 +129,7 @@ int main(void) {
// Stack limit should be less than real stack size, so we have a chance
// to recover from limit hit.
mp_stack_set_top(&_estack);
mp_stack_set_limit((char *)&_estack - (char *)&_heap_end - 1024);
mp_stack_set_limit((char *)&_estack - (char *)&_sstack - 1024);
#if MICROPY_ENABLE_PYSTACK
static mp_obj_t pystack[1024];
@ -179,10 +179,14 @@ void HardFault_Handler(void) {
error_shutdown("Internal error", "(HF)", NULL, NULL);
}
void MemManage_Handler(void) {
void MemManage_Handler_MM(void) {
error_shutdown("Internal error", "(MM)", NULL, NULL);
}
void MemManage_Handler_SO(void) {
error_shutdown("Internal error", "(SO)", NULL, NULL);
}
void BusFault_Handler(void) {
error_shutdown("Internal error", "(BF)", NULL, NULL);
}

View File

@ -7,7 +7,8 @@ MEMORY {
SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 128K
}
main_stack_base = ORIGIN(SRAM) + LENGTH(SRAM); /* 8-byte aligned full descending stack */
main_stack_base = ORIGIN(SRAM) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
_sstack = ORIGIN(SRAM);
_estack = main_stack_base;
/* used by the startup code to populate variables used by the C code */
@ -52,6 +53,10 @@ SECTIONS {
. = ALIGN(4);
} >FLASH AT>FLASH
.stack : ALIGN(8) {
. = 16K; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
} >SRAM
.data : ALIGN(4) {
*(.data*);
. = ALIGN(512);
@ -64,10 +69,6 @@ SECTIONS {
.heap : ALIGN(4) {
. = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */
. = ABSOLUTE(sram_end - 16K); /* this explicitly sets the end of the heap effectively giving the stack at most 16K */
} >SRAM
.stack : ALIGN(8) {
. = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */
. = ABSOLUTE(sram_end - 8); /* this explicitly sets the end of the heap, T1 bootloader had 8 bytes reserved at end */
} >SRAM
}

View File

@ -7,7 +7,8 @@ MEMORY {
SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 128K
}
main_stack_base = ORIGIN(SRAM) + LENGTH(SRAM); /* 8-byte aligned full descending stack */
main_stack_base = ORIGIN(SRAM) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
_sstack = ORIGIN(SRAM);
_estack = main_stack_base;
/* used by the startup code to populate variables used by the C code */
@ -52,6 +53,10 @@ SECTIONS {
. = ALIGN(4);
} >FLASH AT>FLASH
.stack : ALIGN(8) {
. = 16K; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
} >SRAM
.data : ALIGN(4) {
*(.data*);
. = ALIGN(512);
@ -64,10 +69,6 @@ SECTIONS {
.heap : ALIGN(4) {
. = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */
. = ABSOLUTE(sram_end - 16K); /* this explicitly sets the end of the heap effectively giving the stack at most 16K */
} >SRAM
.stack : ALIGN(8) {
. = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */
. = ABSOLUTE(sram_end - 8); /* this explicitly sets the end of the heap, T1 bootloader had 8 bytes reserved at end */
} >SRAM
}

View File

@ -9,7 +9,8 @@ MEMORY {
SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K
}
main_stack_base = ORIGIN(SRAM) + LENGTH(SRAM); /* 8-byte aligned full descending stack */
main_stack_base = ORIGIN(SRAM) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
_sstack = ORIGIN(SRAM);
_estack = main_stack_base;
/* used by the startup code to populate variables used by the C code */
@ -62,6 +63,10 @@ SECTIONS {
. = ALIGN(512);
} >FLASH AT>FLASH
.stack : ALIGN(8) {
. = 16K; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
} >SRAM
.data : ALIGN(4) {
*(.data*);
. = ALIGN(512);
@ -74,10 +79,6 @@ SECTIONS {
.heap : ALIGN(4) {
. = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */
. = ABSOLUTE(sram_end - 16K); /* this explicitly sets the end of the heap effectively giving the stack at most 16K */
} >SRAM
.stack : ALIGN(8) {
. = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */
. = ABSOLUTE(sram_end); /* this explicitly sets the end of the heap */
} >SRAM
}

View File

@ -16,7 +16,7 @@ reset_handler:
ldr r1, =0x08010400 // r1 = FLASH_APP_START
str r1, [r0] // assign
ldr r0, =_estack - 8 // r0 = stack pointer, T1 bootloader had 8 bytes reserved at end
ldr r0, =_estack // r0 = stack pointer
msr msp, r0 // set stack pointer
dsb
isb
@ -59,4 +59,16 @@ reset_handler:
b shutdown_privileged
.global MemManage_Handler
.type MemManage_Handler, STT_FUNC
MemManage_Handler:
ldr r2, =_sstack
mrs r1, msp
ldr r0, =_estack
msr msp, r0
cmp r1, r2
IT lt
bllt MemManage_Handler_SO
bl MemManage_Handler_MM
.end

View File

@ -16,8 +16,14 @@ static inline uint32_t is_mode_unprivileged(void) {
return r0 & 1;
}
static inline uint32_t is_mode_handler(void) {
uint32_t r0;
__asm__ volatile("mrs %0, ipsr" : "=r"(r0));
return (r0 & 0x1FF) != 0;
}
static inline void svc_enableIRQ(uint32_t IRQn) {
if (is_mode_unprivileged()) {
if (is_mode_unprivileged() && !is_mode_handler()) {
register uint32_t r0 __asm__("r0") = IRQn;
__asm__ __volatile__("svc %0" ::"i"(SVC_ENABLE_IRQ), "r"(r0) : "memory");
} else {
@ -26,7 +32,7 @@ static inline void svc_enableIRQ(uint32_t IRQn) {
}
static inline void svc_disableIRQ(uint32_t IRQn) {
if (is_mode_unprivileged()) {
if (is_mode_unprivileged() && !is_mode_handler()) {
register uint32_t r0 __asm__("r0") = IRQn;
__asm__ __volatile__("svc %0" ::"i"(SVC_DISABLE_IRQ), "r"(r0) : "memory");
} else {
@ -35,7 +41,7 @@ static inline void svc_disableIRQ(uint32_t IRQn) {
}
static inline void svc_setpriority(uint32_t IRQn, uint32_t priority) {
if (is_mode_unprivileged()) {
if (is_mode_unprivileged() && !is_mode_handler()) {
register uint32_t r0 __asm__("r0") = IRQn;
register uint32_t r1 __asm__("r1") = priority;
__asm__ __volatile__("svc %0" ::"i"(SVC_SET_PRIORITY), "r"(r0), "r"(r1)
@ -46,14 +52,14 @@ static inline void svc_setpriority(uint32_t IRQn, uint32_t priority) {
}
static inline void svc_shutdown(void) {
if (is_mode_unprivileged()) {
if (is_mode_unprivileged() && !is_mode_handler()) {
__asm__ __volatile__("svc %0" ::"i"(SVC_SHUTDOWN) : "memory");
} else {
shutdown_privileged();
}
}
static inline void svc_reboot_to_bootloader(void) {
if (is_mode_unprivileged()) {
if (is_mode_unprivileged() && !is_mode_handler()) {
__asm__ __volatile__("svc %0" ::"i"(SVC_REBOOT_TO_BOOTLOADER) : "memory");
} else {
reboot_to_bootloader();