fix(core): enable applet before accessing its stack
What changed, and why it matters
This commit fixes a low-level bug in the Trezor hardware wallet's core firmware. Before pushing data onto a task's stack, the code now ensures the correct memory protection region (called an 'applet') is activated. Without this fix, the device could potentially access or corrupt memory it shouldn't while managing internal tasks, which on a security device like a hardware wallet could undermine isolation between sensitive operations.
Treat as a security-relevant hardening fix. Review whether `systask_pop_data`, context-switch paths, and other stack-manipulation sites also need `mpu_set_active_applet()` calls. Verify that the fix is backported to all supported firmware branches and consider whether the issue is reachable from untrusted code (e.g., third-party applets).
Security signals we found
Memory Protection Unit (MPU) context mismatch before stack write
Potential applet isolation bypass or fault
Kernel-only code path guarded by #ifdef KERNEL
No changelog entry despite security-relevant area
Evidence from the diff
In core/embed/sys/task/stm32/systask.c, systask_push_call() now calls mpu_set_active_applet() when task->applet is non-NULL before manipulating the task’s stack pointer. The function then writes to the stack (pushing return address, entrypoint, arguments, and context). The change suggests that previously the MPU region for the applet was not guaranteed to be active during this stack write, which could lead to a memory protection fault or to writes landing in an unintended memory region if the active MPU context did not cover task->sp.
Changed components
core/embed/sys/task/stm32/systask.csystask_push_call()applet/MPU memory layout managementInspect captured patch +7 / −0
diff --git a/core/embed/sys/task/stm32/systask.c b/core/embed/sys/task/stm32/systask.c
index 63204313f..04cb9def2 100644
--- a/core/embed/sys/task/stm32/systask.c
+++ b/core/embed/sys/task/stm32/systask.c
@@ -210,6 +210,13 @@ void systask_pop_data(systask_t* task, size_t size) { task->sp += size; }
bool systask_push_call(systask_t* task, void* entrypoint, uint32_t arg1,
uint32_t arg2, uint32_t arg3) {
+#ifdef KERNEL
+ if (task->applet != NULL) {
+ applet_t* applet = (applet_t*)task->applet;
+ mpu_set_active_applet(&applet->layout);
+ }
+#endif
+
uint32_t original_sp = task->sp;
// Align stack pointer to 8 bytes
Why this scored 57/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.