fix(core/embed): bound bond count before sizing the BLE bond list probe
What changed, and why it matters
This commit fixes a kernel-level memory overflow bug in the Trezor firmware's Bluetooth system. A malicious applet running on the device could request a huge number of Bluetooth 'bond' records, causing a size calculation to wrap around due to 32-bit arithmetic limits. The kernel would then write far more data than the memory area it had verified was safe, potentially overwriting other memory. The fix rejects any request larger than the maximum number of bonds the system actually supports.
Treat this as a security fix and include it in the next firmware release. Backport to supported branches. Review other syscall verifiers for similar 32-bit size_t overflow patterns. Consider adding static analysis or fuzzing rules targeting `probe_write_access`/`probe_read_access` size arguments.
Security signals we found
Integer overflow in size calculation leading to out-of-bounds write
Kernel syscall verifier bypass
Trusted kernel writes attacker-influenced data past verified buffer boundary
Memory safety violation in Bluetooth bond list syscall
Evidence from the diff
In ble_get_bond_list__verified(), the size calculation sizeof(bt_le_addr_t) * count is performed using a 32-bit size_t. For a sufficiently large count, this multiplication overflows and wraps to a small value. The underlying ble_get_bond_list() ignores count on this path and always copies BLE_MAX_BONDS entries. Consequently, the kernel writes up to BLE_MAX_BONDS * sizeof(bt_le_addr_t) bytes into a user-supplied buffer that was only probed for the wrapped (much smaller) size, resulting in an out-of-bounds write. The patch adds an explicit overflow check (count > SIZE_MAX / sizeof(*bonds)) before the probe, and the commit message notes that counts above BLE_MAX_BONDS are rejected elsewhere. This is a kernel syscall verifier bypass in an embedded secure-element-like environment.
Changed components
core/embed/sys/syscall/stm32/syscall_verifiers.cble_get_bond_list__verified() syscall verifierBluetooth LE bond list kernel interfaceInspect captured patch +6 / −1
### core/embed/sys/syscall/stm32/syscall_verifiers.c
@@ -1019,7 +1019,12 @@ bool ble_unpair__verified(const bt_le_addr_t *addr) {
}
uint8_t ble_get_bond_list__verified(bt_le_addr_t *bonds, size_t count) {
- if (!probe_write_access(bonds, sizeof(bt_le_addr_t) * count)) {
+ // Reject counts for which the size below would overflow
+ if (count > SIZE_MAX / sizeof(*bonds)) {
+ goto access_violation;
+ }
+
+ if (!probe_write_access(bonds, sizeof(*bonds) * count)) {
goto access_violation;
}
Why this scored 70/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.