fix(core): remove unnecessary exit handlers
What changed, and why it matters
This commit cleans up how the Trezor firmware emulator (Unix build) shuts down its fake SD card and flash memory. Previously, these emulated memory buffers were automatically unmapped when the program exited via atexit handlers. The commit removes those automatic exit handlers and instead exposes explicit cleanup functions (sdcard_deinit, flash_deinit) that callers can invoke directly. The display emulator also loses its atexit-based deinit. This is a code-quality and resource-management change; it does not appear to fix an exploitable security vulnerability.
No immediate security action required. Treat as routine maintenance. If reviewing the broader emulator lifecycle, verify that the new sdcard_deinit/flash_deinit functions are actually called on emulator shutdown to avoid leaking mapped memory in long-running test processes.
Security signals we found
Removal of atexit cleanup handlers in emulator code
Addition of explicit deinit APIs for sdcard and flash Unix emulators
No changes to secrets, crypto, authentication, or hardware security boundaries
No mention of vulnerability, CVE, researcher, or security fix in commit message
Evidence from the diff
The patch removes atexit-registered cleanup routines in three Unix emulator components: display_driver.c, sdcard.c, and flash.c. It replaces the SD card and flash exit handlers with public deinit functions declared in the corresponding headers. The display driver simply drops its atexit(display_exit_handler) call. The change shifts cleanup responsibility from implicit process-exit callbacks to explicit callers. No logic changes to memory mapping, permissions, secrets handling, or cryptographic operations are present. The commit message is ‘[no changelog]’ and gives no security framing.
Changed components
core/embed/io/display/unix/display_driver.ccore/embed/io/sdcard/inc/io/sdcard.hcore/embed/io/sdcard/unix/sdcard.ccore/embed/sys/flash/inc/sys/flash.hcore/embed/sys/flash/unix/flash.cInspect captured patch +14 / −18
diff --git a/core/embed/io/display/unix/display_driver.c b/core/embed/io/display/unix/display_driver.c
index 8693de4e1..d57c060a7 100644
--- a/core/embed/io/display/unix/display_driver.c
+++ b/core/embed/io/display/unix/display_driver.c
@@ -101,10 +101,6 @@ static display_driver_t g_display_driver = {
int sdl_display_res_x = DISPLAY_RESX, sdl_display_res_y = DISPLAY_RESY;
int sdl_touch_offset_x, sdl_touch_offset_y;
-static void display_exit_handler(void) {
- display_deinit(DISPLAY_RESET_CONTENT);
-}
-
bool display_init(display_content_mode_t mode) {
display_driver_t *drv = &g_display_driver;
@@ -116,7 +112,6 @@ bool display_init(display_content_mode_t mode) {
LOG_ERR("%s", SDL_GetError());
error_shutdown("SDL_Init error");
}
- atexit(display_exit_handler);
char *window_title = NULL;
char *window_title_alloc = NULL;
diff --git a/core/embed/io/sdcard/inc/io/sdcard.h b/core/embed/io/sdcard/inc/io/sdcard.h
index 47853c5be..221ad4f9c 100644
--- a/core/embed/io/sdcard/inc/io/sdcard.h
+++ b/core/embed/io/sdcard/inc/io/sdcard.h
@@ -54,6 +54,9 @@
#ifdef KERNEL_MODE
void sdcard_init(void);
+
+void sdcard_deinit(void);
+
secbool __wur sdcard_power_on_unchecked(bool low_speed);
#endif
diff --git a/core/embed/io/sdcard/unix/sdcard.c b/core/embed/io/sdcard/unix/sdcard.c
index 4f1604931..f120fc7b8 100644
--- a/core/embed/io/sdcard/unix/sdcard.c
+++ b/core/embed/io/sdcard/unix/sdcard.c
@@ -39,12 +39,6 @@
static uint8_t *sdcard_buffer = NULL;
static secbool sdcard_powered = secfalse;
-static void sdcard_exit(void) {
- int r = munmap(sdcard_buffer, SDCARD_SIZE);
- ensure(sectrue * (r == 0), "munmap failed");
- sdcard_buffer = NULL;
-}
-
void sdcard_init(void) {
if (sdcard_buffer != NULL) {
return;
@@ -81,8 +75,12 @@ void sdcard_init(void) {
}
sdcard_powered = secfalse;
+}
- atexit(sdcard_exit);
+void sdcard_deinit(void) {
+ int r = munmap(sdcard_buffer, SDCARD_SIZE);
+ ensure(sectrue * (r == 0), "munmap failed");
+ sdcard_buffer = NULL;
}
secbool sdcard_is_present(void) { return sectrue; }
diff --git a/core/embed/sys/flash/inc/sys/flash.h b/core/embed/sys/flash/inc/sys/flash.h
index 43d22f189..69da925a1 100644
--- a/core/embed/sys/flash/inc/sys/flash.h
+++ b/core/embed/sys/flash/inc/sys/flash.h
@@ -30,6 +30,8 @@
void flash_init(void);
+void flash_deinit(void);
+
extern const flash_area_t BOARDLOADER_AREA;
extern const flash_area_t SECRET_AREA;
extern const flash_area_t BHK_AREA;
diff --git a/core/embed/sys/flash/unix/flash.c b/core/embed/sys/flash/unix/flash.c
index 79eeb44c1..ef8925b53 100644
--- a/core/embed/sys/flash/unix/flash.c
+++ b/core/embed/sys/flash/unix/flash.c
@@ -82,11 +82,6 @@ static uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
static uint8_t *FLASH_BUFFER = NULL;
static uint32_t FLASH_SIZE;
-static void flash_exit(void) {
- int r = munmap(FLASH_BUFFER, FLASH_SIZE);
- ensure(sectrue * (r == 0), "munmap failed");
-}
-
void flash_init(void) {
if (FLASH_BUFFER) return;
@@ -126,8 +121,11 @@ void flash_init(void) {
ensure(sectrue * (map != MAP_FAILED), "mmap failed");
FLASH_BUFFER = (uint8_t *)map;
+}
- atexit(flash_exit);
+void flash_deinit(void) {
+ int r = munmap(FLASH_BUFFER, FLASH_SIZE);
+ ensure(sectrue * (r == 0), "munmap failed");
}
secbool flash_unlock_write(void) { return sectrue; }
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.