Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve stack protection on STM32U5 #3402

Merged
merged 1 commit into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/SConscript.bootloader_emu
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ SOURCE_BOOTLOADER = [
SOURCE_TREZORHAL = [
'embed/trezorhal/unix/boot_args.c',
'embed/trezorhal/unix/display-unix.c',
'embed/trezorhal/unix/fault_handlers.c',
'embed/trezorhal/unix/flash.c',
'embed/trezorhal/unix/common.c',
'embed/trezorhal/unix/touch/touch.c',
Expand Down
3 changes: 3 additions & 0 deletions core/embed/boardloader/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "common.h"
#include "compiler_traits.h"
#include "display.h"
#include "fault_handlers.h"
#include "flash.h"
#include "image.h"
#include "model.h"
Expand Down Expand Up @@ -256,6 +257,8 @@ int main(void) {

mpu_config_boardloader();

fault_handlers_init();

#ifdef USE_SDRAM
sdram_init();
#endif
Expand Down
4 changes: 2 additions & 2 deletions core/embed/boardloader/memory_stm32u5a.ld
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ MEMORY {
}

main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
_sstack = ORIGIN(SRAM2) + 0x100;
_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;

/* used by the startup code to populate variables used by the C code */
Expand Down Expand Up @@ -80,7 +80,7 @@ SECTIONS {
} >SRAM1

.stack : ALIGN(8) {
. = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
. = 16K; /* Overflow causes UsageFault */
} >SRAM2

.sensitive : ALIGN(8) {
Expand Down
5 changes: 5 additions & 0 deletions core/embed/boardloader/startup_stm32u5.s
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
// set the stack protection
ldr r0, =_sstack
add r0, r0, #16 // padding
msr MSPLIM, r0

bl SystemInit

// read the first rng data and save it
Expand Down
3 changes: 3 additions & 0 deletions core/embed/bootloader/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "boot_args.h"
#include "common.h"
#include "display.h"
#include "fault_handlers.h"
#include "flash.h"
#include "image.h"
#include "lowlevel.h"
Expand Down Expand Up @@ -423,6 +424,8 @@ int bootloader_main(void) {

mpu_config_bootloader();

fault_handlers_init();

#ifdef TREZOR_EMULATOR
// wait a bit so that the empty lock icon is visible
// (on a real device, we are waiting for touch init which takes longer)
Expand Down
4 changes: 2 additions & 2 deletions core/embed/bootloader/memory_stm32u5a.ld
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ MEMORY {
}

main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
_sstack = ORIGIN(SRAM2) + 0x100;
_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;

/* used by the startup code to populate variables used by the C code */
Expand Down Expand Up @@ -81,7 +81,7 @@ SECTIONS {
} >SRAM1

.stack : ALIGN(8) {
. = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
. = 16K; /* Overflow causes UsageFault */
} >SRAM2

.sensitive : ALIGN(512) {
Expand Down
5 changes: 5 additions & 0 deletions core/embed/bootloader/startup_stm32u5.s
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
// set the stack protection
ldr r0, =_sstack
add r0, r0, #16 // padding
msr MSPLIM, r0

// setup environment for subsequent stage of code
ldr r2, =0 // r2 - the word-sized value to be written

Expand Down
4 changes: 2 additions & 2 deletions core/embed/bootloader_ci/memory_stm32u5a.ld
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ MEMORY {
}

main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
_sstack = ORIGIN(SRAM2) + 0x100;
_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;

/* used by the startup code to populate variables used by the C code */
Expand Down Expand Up @@ -81,7 +81,7 @@ SECTIONS {
} >SRAM1

.stack : ALIGN(8) {
. = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
. = 16K; /* Overflow causes UsageFault */
} >SRAM2

.sensitive : ALIGN(512) {
Expand Down
5 changes: 5 additions & 0 deletions core/embed/bootloader_ci/startup_stm32u5.s
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
// set the stack protection
ldr r0, =_sstack
add r0, r0, #16 // padding
msr MSPLIM, r0

// setup environment for subsequent stage of code
ldr r2, =0 // r2 - the word-sized value to be written

Expand Down
6 changes: 2 additions & 4 deletions core/embed/firmware/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "common.h"
#include "compiler_traits.h"
#include "display.h"
#include "fault_handlers.h"
#include "flash.h"
#include "image.h"
#include "memzero.h"
Expand Down Expand Up @@ -143,10 +144,7 @@ int main(void) {
dma2d_init();
#endif

#if !PRODUCTION
// enable BUS fault and USAGE fault handlers
SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
#endif
fault_handlers_init();

#if defined TREZOR_MODEL_T
set_core_clock(CLOCK_180_MHZ);
Expand Down
4 changes: 2 additions & 2 deletions core/embed/firmware/memory_DISC2.ld
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ MEMORY {
}

main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
_sstack = ORIGIN(SRAM2) + 0x100;
_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;

/* used by the startup code to populate variables used by the C code */
Expand Down Expand Up @@ -97,7 +97,7 @@ SECTIONS {
} >SRAM1

.stack : ALIGN(8) {
. = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
. = 16K; /* Overflow causes UsageFault */
} >SRAM2

.sensitive : ALIGN(512) {
Expand Down
5 changes: 5 additions & 0 deletions core/embed/firmware/startup_stm32u5.S
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
// set the stack protection
ldr r0, =_sstack
add r0, r0, #16 // padding
msr MSPLIM, r0

// setup environment for subsequent stage of code
ldr r2, =0 // r2 - the word-sized value to be written

Expand Down
3 changes: 3 additions & 0 deletions core/embed/prodtest/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "button.h"
#include "common.h"
#include "display.h"
#include "fault_handlers.h"
#include "flash.h"
#include "i2c.h"
#include "model.h"
Expand Down Expand Up @@ -569,6 +570,8 @@ int main(void) {
#endif

mpu_config_prodtest();
fault_handlers_init();

drop_privileges();

display_clear();
Expand Down
4 changes: 2 additions & 2 deletions core/embed/prodtest/memory_stm32u5a.ld
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ MEMORY {
}

main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
_sstack = ORIGIN(SRAM2) + 0x100;
_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;

/* used by the startup code to populate variables used by the C code */
Expand Down Expand Up @@ -96,7 +96,7 @@ SECTIONS {
} >SRAM1

.stack : ALIGN(8) {
. = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
. = 16K; /* Overflow causes UsageFault */
} >SRAM2

.sensitive : ALIGN(512) {
Expand Down
5 changes: 5 additions & 0 deletions core/embed/prodtest/startup_stm32u5.s
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
// set the stack protection
ldr r0, =_sstack
add r0, r0, #16 // padding
msr MSPLIM, r0

// setup environment for subsequent stage of code
ldr r2, =0 // r2 - the word-sized value to be written

Expand Down
4 changes: 2 additions & 2 deletions core/embed/reflash/memory_stm32u5a.ld
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ MEMORY {
}

main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
_sstack = ORIGIN(SRAM2) + 0x100;
_sstack = ORIGIN(SRAM2);
_estack = main_stack_base;

/* used by the startup code to populate variables used by the C code */
Expand Down Expand Up @@ -97,7 +97,7 @@ SECTIONS {
} >SRAM1

.stack : ALIGN(8) {
. = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
. = 16K + 0x100; /* Overflow causes UsageFault */
} >SRAM2

.sensitive : ALIGN(512) {
Expand Down
5 changes: 5 additions & 0 deletions core/embed/reflash/startup_stm32u5.s
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
.global reset_handler
.type reset_handler, STT_FUNC
reset_handler:
// set the stack protection
ldr r0, =_sstack
add r0, r0, #16 // padding
msr MSPLIM, r0

// setup environment for subsequent stage of code
ldr r2, =0 // r2 - the word-sized value to be written

Expand Down
7 changes: 7 additions & 0 deletions core/embed/trezorhal/fault_handlers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef TREZORHAL_FAULT_HANDLERS_H
#define TREZORHAL_FAULT_HANDLERS_H

// Initializes and enables fault handlers
void fault_handlers_init(void);

#endif // TREZORHAL_FAULT_HANDLERS_H
5 changes: 5 additions & 0 deletions core/embed/trezorhal/stm32f4/fault_handlers.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#include "common.h"

void fault_handlers_init(void) {
// Enable BUS fault and USAGE fault handlers
SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
}

void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }

void MemManage_Handler_MM(void) { error_shutdown("INTERNAL ERROR", "(MM)"); }
Expand Down
22 changes: 18 additions & 4 deletions core/embed/trezorhal/stm32u5/fault_handlers.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
#include "common.h"

void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }
void fault_handlers_init(void) {
// Enable BUS fault and USAGE fault handlers
SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
}

void MemManage_Handler_MM(void) { error_shutdown("INTERNAL ERROR", "(MM)"); }
void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }

void MemManage_Handler_SO(void) { error_shutdown("INTERNAL ERROR", "(SO)"); }
void MemManage_Handler(void) { error_shutdown("INTERNAL ERROR", "(MM)"); }

void BusFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(BF)"); }

void UsageFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(UF)"); }
void UsageFault_Handler(void) {
if (SCB->CFSR & SCB_CFSR_STKOF_Msk) {
// Stack overflow
extern uint8_t _estack; // linker script symbol
// Fix stack pointer
__set_MSP((uint32_t)&_estack);
error_shutdown("INTERNAL ERROR", "(SO)");
} else {
// Other error
error_shutdown("INTERNAL ERROR", "(UF)");
}
}

void SecureFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(SF)"); }

Expand Down
12 changes: 0 additions & 12 deletions core/embed/trezorhal/stm32u5/limited_util.s
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,4 @@ shutdown_privileged:
ldr r0, =0
b . // loop forever

.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
31 changes: 15 additions & 16 deletions core/embed/trezorhal/stm32u5/mpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ static void mpu_set_attributes() {
#define SIZE_128K (128 * 1024)
#define SIZE_192K (192 * 1024)
#define SIZE_320K (320 * 1024)
#define SIZE_768K (768 * 1024)
#define SIZE_1728K ((832 * 2 + 64) * 1024)
#define SIZE_2496K (2496 * 1024)
#define SIZE_3776K ((4096 - 320) * 1024)
#define SIZE_3904K ((4096 - 192) * 1024)
#define SIZE_4032K ((4096 - 64) * 1024)
Expand All @@ -131,10 +130,10 @@ void mpu_config_boardloader() {
SET_REGION( 0, FLASH_BASE_S, SIZE_16K, FLASH_DATA, YES, NO ); // Secret
SET_REGION( 1, FLASH_BASE_S + SIZE_16K, SIZE_48K, FLASH_CODE, NO, NO ); // Boardloader code
SET_REGION( 2, FLASH_BASE_S + SIZE_64K, SIZE_4032K, FLASH_DATA, YES, NO ); // Bootloader + Storage + Firmware
SET_REGION( 3, SRAM1_BASE_S, SIZE_768K, SRAM, YES, NO ); // SRAM1
SET_REGION( 4, SRAM2_BASE_S + 0x100, SIZE_1728K - 0x100, SRAM, YES, NO ); // SRAM2/3/5 + stack guard
SET_REGION( 5, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, NO ); // Frame buffer
SET_REGION( 6, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, NO ); // Peripherals
SET_REGION( 3, SRAM1_BASE_S, SIZE_2496K, SRAM, YES, NO ); // SRAM1/2/3/5
SET_REGION( 4, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, NO ); // Frame buffer
SET_REGION( 5, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, NO ); // Peripherals
DIS_REGION( 6 );
DIS_REGION( 7 );
// clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
Expand All @@ -148,11 +147,11 @@ void mpu_config_bootloader() {
SET_REGION( 0, FLASH_BASE_S, SIZE_64K, FLASH_DATA, YES, NO ); // Secret + Boardloader
SET_REGION( 1, FLASH_BASE_S + SIZE_64K, SIZE_128K, FLASH_CODE, NO, NO ); // Bootloader code
SET_REGION( 2, FLASH_BASE_S + SIZE_192K, SIZE_3904K, FLASH_DATA, YES, NO ); // Storage + Firmware
SET_REGION( 3, SRAM1_BASE_S, SIZE_768K, SRAM, YES, NO ); // SRAM1
SET_REGION( 4, SRAM2_BASE_S + 0x100, SIZE_1728K - 0x100, SRAM, YES, NO ); // SRAM2/3/5 + stack guard
SET_REGION( 5, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, NO ); // Frame buffer
SET_REGION( 6, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, NO ); // Peripherals
SET_REGION( 7, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, NO ); // OTP
SET_REGION( 3, SRAM1_BASE_S, SIZE_2496K, SRAM, YES, NO ); // SRAM1/2/3/5
SET_REGION( 4, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, NO ); // Frame buffer
SET_REGION( 5, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, NO ); // Peripherals
SET_REGION( 6, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, NO ); // OTP
DIS_REGION( 7 );
// clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
}
Expand All @@ -164,11 +163,11 @@ void mpu_config_firmware() {
// REGION ADDRESS SIZE TYPE WRITE UNPRIV
SET_REGION( 0, FLASH_BASE_S + SIZE_192K, SIZE_128K, FLASH_DATA, YES, YES ); // Storage
SET_REGION( 1, FLASH_BASE_S + SIZE_320K, SIZE_3776K, FLASH_CODE, NO, YES ); // Firmware
SET_REGION( 2, SRAM1_BASE_S, SIZE_768K, SRAM, YES, YES ); // SRAM1
SET_REGION( 3, SRAM2_BASE_S + 0x100, SIZE_1728K - 0x100, SRAM, YES, YES ); // SRAM2/3/5 + stack guard
SET_REGION( 4, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, YES ); // Frame buffer
SET_REGION( 5, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, YES ); // Peripherals
SET_REGION( 6, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, YES ); // OTP
SET_REGION( 2, SRAM1_BASE_S, SIZE_2496K, SRAM, YES, YES ); // SRAM1/2/3/5
SET_REGION( 3, GFXMMU_BUFFERS_S, SIZE_16M, SRAM, YES, YES ); // Frame buffer
SET_REGION( 4, PERIPH_BASE_S, SIZE_256M, PERIPHERAL, YES, YES ); // Peripherals
SET_REGION( 5, FLASH_OTP_BASE, FLASH_OTP_SIZE, FLASH_DATA, YES, YES ); // OTP
DIS_REGION( 6 );
DIS_REGION( 7 );
// clang-format on
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
Expand Down
Loading
Loading