What changed, and why it matters
This commit fixes how a small on-screen reminder (the 'nudge screen') for U2F is created, tracked, and cleaned up. Before the fix, the code could lose track of the reminder screen or mishandle its removal, which might cause display glitches or memory issues. The patch makes cleanup more reliable by tying the global pointer to the screen's actual destruction.
Treat as a hardening/reliability fix. Review whether the old behavior could lead to a use-after-free or null-deref in U2F flows, and include this commit in any U2F-related regression testing. No immediate emergency action is indicated from the diff alone.
Security signals we found
Use-after-free / dangling-pointer risk: global _nudge_label pointer could outlive the component it references
UI state inconsistency: previous callback set _nudge_label = NULL on screen pop, but component cleanup may occur later or not at all
Memory management fix: custom cleanup wrapper now synchronizes global pointer with component lifetime
Evidence from the diff
The change refactors _create_nudge_label and _nudge_label_cb in src/u2f.c. It introduces a custom component cleanup function that clears the global _nudge_label pointer when the component is destroyed, and assigns a custom component_functions_t to the info_centered component. Previously, the global pointer was set to NULL inside the callback when the screen was popped, which could race or be skipped if cleanup happened elsewhere. The new logic ensures the pointer is invalidated only via the component’s cleanup path and avoids re-creating or re-pushing an already-existing nudge label.
Changed components
src/u2f.cU2F nudge screen UI componentscreen stack managementInspect captured patch +22 / −7
diff --git a/src/u2f.c b/src/u2f.c
index 1af6a76..1e0aa42 100644
--- a/src/u2f.c
+++ b/src/u2f.c
@@ -15,6 +15,7 @@
#include <ui/components/info_centered.h>
#include <ui/screen_process.h>
#include <ui/screen_stack.h>
+#include <ui/ui_util.h>
#include <usb/u2f/u2f.h>
#include <usb/u2f/u2f_hid.h>
#include <usb/u2f/u2f_keys.h>
@@ -120,23 +121,37 @@ static void _clear_state(void)
static component_t* _nudge_label = NULL;
+static void _nudge_label_cleanup(component_t* component)
+{
+ if (_nudge_label == component) {
+ _nudge_label = NULL;
+ }
+ ui_util_component_cleanup(component);
+}
+
+static const component_functions_t _nudge_label_component_functions = {
+ .cleanup = _nudge_label_cleanup,
+ .render = ui_util_component_render_subcomponents,
+ .on_event = NULL,
+};
+
static void _nudge_label_cb(component_t* component)
{
if (ui_screen_stack_top() == component->parent) {
- _nudge_label = NULL;
ui_screen_stack_pop();
}
}
static void _create_nudge_label(void)
{
- if (!_nudge_label) {
- _nudge_label =
- info_centered_create("Initialize with BitBoxApp\nto use U2F", _nudge_label_cb);
- }
- if (ui_screen_stack_top() != _nudge_label) {
- ui_screen_stack_push(_nudge_label);
+ if (_nudge_label) {
+ // The screen stack owns the existing component until its cleanup runs.
+ return;
}
+
+ _nudge_label = info_centered_create("Initialize with BitBoxApp\nto use U2F", _nudge_label_cb);
+ _nudge_label->f = &_nudge_label_component_functions;
+ ui_screen_stack_push(_nudge_label);
}
static void _start_refresh_webpage_screen(void)
Why this scored 27/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.