refactor(core): enable unprivileged access to the framebuffer during kernel init
What changed, and why it matters
This commit moves a security setting for the screen framebuffer from a per-app switching routine to a one-time enable during system startup. It makes the framebuffer permanently accessible to less-privileged code, rather than toggling access on and off as apps start and stop. The change is described by the developer as a refactor and has no changelog entry. On its own it looks like a deliberate design relaxation, not an accidental bug, but it removes a layer of isolation that previously restricted unprivileged tasks from touching display memory.
Treat this as a security-relevant hardening change that should be reviewed by the vendor's security team. Verify whether making the framebuffer permanently unprivileged is intentional and whether compensating controls (e.g., display command restrictions, input validation, secure compositor) mitigate the loss of isolation. If no such controls exist, consider restoring dynamic unprivileged access or documenting the security rationale.
Security signals we found
TrustZone privilege boundary change
framebuffer memory made permanently unprivileged-accessible
removal of dynamic privilege toggle for display memory
no changelog entry despite security-relevant behavior change
commit title frames change as a refactor
Evidence from the diff
In the Trezor kernel’s TrustZone-based architecture, display_set_unpriv_access() controls whether the non-secure/unprivileged world can read/write the display framebuffer. Previously, in coreapp.c, applet_set_unpriv() called display_set_unpriv_access(unpriv) alongside other MPU/TrustZone permission changes when an applet was entering or leaving unprivileged mode. The patch removes that call from applet_set_unpriv() and instead calls display_set_unpriv_access(true) once during drivers_init() in main.c, under USE_TRUSTZONE. The effect is that the framebuffer is unprivileged-accessible throughout kernel init and remains so, instead of being tied to the applet’s privilege state.
Changed components
core/embed/projects/kernel/main.ccore/embed/sys/task/stm32/coreapp.cTrustZone display memory permissionskernel/applet privilege isolationInspect captured patch +4 / −3
diff --git a/core/embed/projects/kernel/main.c b/core/embed/projects/kernel/main.c
index 538b6133..1c72f83d 100644
--- a/core/embed/projects/kernel/main.c
+++ b/core/embed/projects/kernel/main.c
@@ -162,6 +162,10 @@ void drivers_init() {
display_init(DISPLAY_JUMP_BEHAVIOR);
+#ifdef USE_TRUSTZONE
+ display_set_unpriv_access(true);
+#endif
+
#ifdef SECURE_MODE
#ifdef USE_OEM_KEYS_CHECK
option_bytes_check_oem_keys();
diff --git a/core/embed/sys/task/stm32/coreapp.c b/core/embed/sys/task/stm32/coreapp.c
index 653b9b51..bdbe3a56 100644
--- a/core/embed/sys/task/stm32/coreapp.c
+++ b/core/embed/sys/task/stm32/coreapp.c
@@ -30,7 +30,6 @@
#include <sys/systask.h>
#ifdef USE_TRUSTZONE
-#include <io/display.h>
#include <sys/trustzone.h>
#endif
@@ -63,8 +62,6 @@ static void applet_set_unpriv(applet_t* applet, bool unpriv) {
tz_set_flash_unpriv(layout->code2.start, layout->code2.size, unpriv);
tz_set_flash_unpriv(ASSETS_START, ASSETS_MAXSIZE, unpriv);
-
- display_set_unpriv_access(unpriv);
}
#endif // USE_TRUSTZONE
Why this scored 35/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.