fix(emulator): handle systask_push_call() error
What changed, and why it matters
This commit fixes a small but real bug in the Trezor emulator (the desktop/Unix version used for testing, not the real hardware wallet). When the emulator tries to shut down a MicroPython task, it previously ignored whether the internal 'push call' operation succeeded. If that operation failed, the code would still try to switch to the task, potentially leaving the emulator in an inconsistent or hung state. The fix adds an explicit error shutdown if the push fails. It is a hardening fix rather than a clear exploitable vulnerability, and it only affects the Unix emulator build.
Treat as a low-severity hardening fix. Apply the patch in normal development; no urgent security response is warranted based on the diff alone. If auditing, review systask_push_call() callers across the codebase for similar unchecked return values, especially in hardware builds where consequences could be more serious.
Security signals we found
Unchecked return value of internal task-management API
Possible inconsistent task state / emulator hang on failure path
Fix is in emulator-only code (core/embed/projects/unix)
No explicit security claim in commit message or diff
Evidence from the diff
In core/embed/projects/unix/main_main.c, throw_exit_exception() calls systask_push_call() to inject throw_exit_exception_trampoline() into a target systask, then immediately calls systask_yield_to(task). The original code did not check the boolean return value of systask_push_call(). If the push failed (e.g., because the task’s call stack was full or the task was in a state that rejected a new call), the subsequent yield could switch to a task that had not been set up to throw the SystemExit exception, leading to undefined behavior or a hang. The patch checks the return value and calls error_shutdown() on failure. This is a defensive fix in the emulator’s task-lifecycle path.
Changed components
core/embed/projects/unix/main_main.cTrezor firmware Unix emulator buildsystask / MicroPython task teardown pathInspect captured patch +4 / −2
diff --git a/core/embed/projects/unix/main_main.c b/core/embed/projects/unix/main_main.c
index ef8e8dba..2c9686e8 100644
--- a/core/embed/projects/unix/main_main.c
+++ b/core/embed/projects/unix/main_main.c
@@ -111,8 +111,10 @@ static uintptr_t throw_exit_exception_trampoline(uintptr_t code,
// Throws MicroPython SystemExit exception in the context of the given task
static void throw_exit_exception(systask_t *task, int code) {
// Push call to the task
- systask_push_call(task, (void *)throw_exit_exception_trampoline,
- (uintptr_t)code, 0, 0);
+ if (!systask_push_call(task, (void *)throw_exit_exception_trampoline,
+ (uintptr_t)code, 0, 0)) {
+ error_shutdown("Cannot throw exit exception");
+ }
// Yield to the task and throw the exception
systask_yield_to(task);
// We are back and the task should be terminated by now
Why this scored 26/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.