fix(core): correct `ble_enter_pairing_mode()` cleanup
What changed, and why it matters
This commit fixes a subtle cleanup bug in the Bluetooth pairing function on Trezor hardware wallets. Before the fix, if a caller supplied an advertising name that was too long, the function returned early without unlocking an important system lock (irq_lock). Leaving that lock held could freeze or crash the device. The fix moves the length check before the lock is taken, so the bad-input path no longer skips the unlock.
Treat as a low-to-moderate reliability/security fix. Verify that all callers of `ble_enter_pairing_mode()` pass length-checked names, and confirm the IRQ lock is paired correctly on every remaining code path. No immediate CVE is indicated by the commit alone; consider a security note if the function is reachable from untrusted input.
Security signals we found
Resource/lock leak on error path
IRQ lock held across early return
Length validation reordered before lock acquisition
Potential denial-of-service via device freeze/crash if triggerable
Evidence from the diff
In core/embed/io/ble/stm32/ble.c, ble_enter_pairing_mode() takes irq_key_t key = irq_lock() and then validates name_len. The original code only rejected name_len > BLE_ADV_NAME_LEN after acquiring the lock, returning false without calling irq_unlock(key). The patch relocates the oversized-name check above the irq_lock() acquisition and simplifies the subsequent validation. This ensures the error path cannot leak the IRQ lock. The change is small and appears correct, but the diff alone does not show whether any caller actually passes an over-long name or whether the bug is reachable from user-facing code.
Changed components
core/embed/io/ble/stm32/ble.cble_enter_pairing_mode()Trezor Core Bluetooth LE driverInspect captured patch +5 / −3
diff --git a/core/embed/io/ble/stm32/ble.c b/core/embed/io/ble/stm32/ble.c
index fdc05c3a..7af80ce1 100644
--- a/core/embed/io/ble/stm32/ble.c
+++ b/core/embed/io/ble/stm32/ble.c
@@ -1009,13 +1009,15 @@ bool ble_enter_pairing_mode(const uint8_t *name, size_t name_len) {
return false;
}
+ if (name_len > BLE_ADV_NAME_LEN) {
+ return false;
+ }
+
irq_key_t key = irq_lock();
- if (name != NULL && name_len > 0 && name_len <= BLE_ADV_NAME_LEN) {
+ if (name != NULL && name_len > 0) {
memset(drv->adv_name, 0, sizeof(drv->adv_name));
memcpy(drv->adv_name, name, name_len);
- } else if (name != NULL && name_len > BLE_ADV_NAME_LEN) {
- return false;
}
drv->restart_adv_on_disconnect = true;
Why this scored 42/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.