feat(core): register IPC buffer for extapp remote
What changed, and why it matters
This change moves the registration of an inter-process communication (IPC) buffer for the coreapp from a script that can run multiple times (run.py) to the firmware's startup code, which runs only once per boot. The goal is to prevent re-registration from resetting the message queue while an external app is still using it. The change itself is defensive and appears to fix a stability or potential security issue caused by repeated registration.
Review the prior implementation in run.py to confirm the re-registration path is fully removed and cannot be triggered elsewhere. Audit `ipc_register` behavior to ensure it is idempotent or fails safely if called again. Consider whether a running extapp could exploit the window before registration or a missing registration.
Security signals we found
IPC buffer re-registration could reset kernel queue under a running extapp
Fix prevents potential state corruption or denial of service during extapp orchestration
Change is defensive and hardens IPC lifecycle management
No explicit vulnerability disclosure or CVE referenced in commit
Evidence from the diff
The commit introduces a new header coreapp_ipc.h defining IPC_REMOTE_EXTAPP (task ID 2) and IPC_COREAPP_BUFFER_SIZE (32 KB). It then registers this buffer once at coreapp startup in both the STM32 and Unix main.c files via ipc_register(IPC_REMOTE_EXTAPP, ipc_buffer, sizeof(ipc_buffer)), guarded by #if USE_IPC. Previously, this registration was apparently done in run.py, which can be invoked multiple times per boot; re-registration would reset the kernel queue and corrupt state for a running extapp. The patch is a relocation/fix of IPC lifecycle management.
Changed components
core/embed/projects/firmware/src/coreapp_ipc.hcore/embed/projects/firmware/src/stm32/main.ccore/embed/projects/firmware/src/unix/main.cTrezor coreapp IPC subsystemExternal app (extapp) loading/orchestrationInspect captured patch +71 / −2
### core/embed/projects/firmware/src/coreapp_ipc.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <sys/systask.h>
+
+/**
+ * Task the coreapp exchanges IPC messages with.
+ *
+ * Task IDs are zero-based indices (see `systask_id_t`): 0 is the kernel, 1 the
+ * coreapp itself, 2 the loaded user app. Only meaningful with `USE_APP_LOADING`
+ * enabled, which is also what raises `SYSTASK_MAX_TASKS` to 3.
+ *
+ * TODO: replace with a task id obtained from the applet/app-arena layer once
+ * one is exposed, rather than assuming the single extapp slot.
+ */
+#define IPC_REMOTE_EXTAPP ((systask_id_t)2)
+// Size of the IPC receive buffer registered by the coreapp
+#define IPC_COREAPP_BUFFER_SIZE (32 * 1024)
### core/embed/projects/firmware/src/stm32/main.c
@@ -37,16 +37,16 @@
#include <io/notify.h>
#include <io/rsod.h>
#include <sec/boot_image.h>
+#include <sys/bootutils.h>
#include <sys/linker_utils.h>
#include <sys/logging.h>
#include <sys/systask.h>
#include <sys/system.h>
+
#include "rust_ui_common.h"
#include <blake2s.h>
-#include "sys/bootutils.h"
-
#ifdef USE_SECP256K1_ZKP
#include "zkp_context.h"
#endif
@@ -55,6 +55,12 @@
#include <io/ble.h>
#endif
+#ifdef USE_IPC
+#include <sys/ipc.h>
+
+#include "../coreapp_ipc.h"
+#endif
+
#ifdef USE_NRF
#include <io/nrf.h>
@@ -66,13 +72,24 @@ extern const void nrf_app_size;
LOG_DECLARE(coreapp_main)
+#if USE_IPC
+uint32_t ipc_buffer[IPC_COREAPP_BUFFER_SIZE / sizeof(uint32_t)];
+#endif
+
int main_func(uint32_t cmd, void *arg) {
if (cmd == 1) {
systask_postmortem_t *info = (systask_postmortem_t *)arg;
rsod_gui(info);
system_exit(0);
}
+#if USE_IPC
+ // Registered once for the coreapp's lifetime: re-registering while an
+ // extapp is running would reset the queue under it, so this is not
+ // something extapp orchestration (e.g. run.py) is allowed to repeat.
+ ipc_register(IPC_REMOTE_EXTAPP, ipc_buffer, sizeof(ipc_buffer));
+#endif
+
bool fading = DISPLAY_JUMP_BEHAVIOR == DISPLAY_RESET_CONTENT;
bool update_required = false;
### core/embed/projects/firmware/src/unix/main.c
@@ -67,6 +67,12 @@
#include "shared/runtime/pyexec.h"
#include "stack_size.h"
+#ifdef USE_IPC
+#include <sys/ipc.h>
+
+#include "../coreapp_ipc.h"
+#endif
+
// Command line options, with their defaults
bool mp_compile_only = false;
static uint emit_opt = MP_EMIT_OPT_NONE;
@@ -787,7 +793,17 @@ MP_NOINLINE int main_(int argc, char **argv) {
return ret & 0xff;
}
+#if USE_IPC
+uint32_t ipc_buffer[IPC_COREAPP_BUFFER_SIZE / sizeof(uint32_t)];
+#endif
+
int coreapp_emu(int argc, char **argv) {
+#if USE_IPC
+ // Registered once for the coreapp's lifetime; see the stm32 main.c for why
+ // this isn't repeated per extapp launch.
+ ipc_register(IPC_REMOTE_EXTAPP, ipc_buffer, sizeof(ipc_buffer));
+#endif
+
#if MICROPY_PY_THREAD
mp_thread_init();
#endifWhy this scored 32/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.