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:
parent
459270ef3f
commit
6cf92fd748
1
core/.changelog.d/2427.added
Normal file
1
core/.changelog.d/2427.added
Normal file
@ -0,0 +1 @@
|
||||
Add stack overflow detection
|
1
core/embed/bootloader/.changelog.d/2427.added
Normal file
1
core/embed/bootloader/.changelog.d/2427.added
Normal file
@ -0,0 +1 @@
|
||||
Add stack overflow detection
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user