fix(core): refuse an emulator BLE read that cannot take a whole packet
What changed, and why it matters
This commit fixes a bug in the Trezor emulator's Bluetooth-over-UDP code. Previously, if a caller asked to read a Bluetooth packet into a buffer smaller than a full packet, the emulator would silently throw away the leftover data. Now it refuses short reads up front, matching a fix already made in the real hardware driver. The commit message says no real callers were affected because all normal callers use full-size buffers.
Treat as a low-severity hardening fix. Verify that all callers of ble_read() indeed use buffers of at least BLE_RX_PACKET_SIZE, and consider adding a static assertion or documentation to maintain this invariant. No urgent action is required unless a direct ble_read() syscall with a short buffer is exposed to untrusted code.
Security signals we found
Data truncation / silent packet loss on datagram socket
Emulator-only code path, but mirrors a hardware driver security fix
Possible inconsistency between returned length and consumed datagram
Defensive bounds check added to refuse undersized reads
Evidence from the diff
In core/embed/io/ble/unix/ble.c, ble_read() previously called sock_recvfrom() with MIN(max_len, sizeof(buf)) on a SOCK_DGRAM socket. Because datagram sockets consume the whole datagram and discard what does not fit, a caller-supplied max_len smaller than BLE_RX_PACKET_SIZE would truncate and lose part of the received packet. The patch adds an explicit max_len < BLE_RX_PACKET_SIZE guard that returns 0, then always reads into the full BLE_RX_PACKET_SIZE stack buffer. This mirrors a corresponding hardware-driver fix and prevents UDP-truncation-style data loss in the emulator.
Changed components
core/embed/io/ble/unix/ble.cTrezor emulator Bluetooth-over-UDP data pathble_read() syscall implementationInspect captured patch +8 / −3
### core/embed/io/ble/unix/ble.c
@@ -451,10 +451,15 @@ uint32_t ble_read(uint8_t *data, uint16_t max_len) {
return 0;
}
- // A packet is the most the hardware driver ever returns, so cap the read
- // there instead of letting `max_len` size a stack allocation.
+ // A datagram is consumed whole, so a caller that cannot take a full packet
+ // has to be refused before the read - otherwise the remainder is discarded.
+ // The hardware driver rejects these for the same reason.
+ if (max_len < BLE_RX_PACKET_SIZE) {
+ return 0;
+ }
+
uint8_t buf[BLE_RX_PACKET_SIZE] = {0};
- ssize_t r = sock_recvfrom(&drv->data_sock, buf, MIN(max_len, sizeof(buf)));
+ ssize_t r = sock_recvfrom(&drv->data_sock, buf, sizeof(buf));
if (r <= 0) {
return 0;
}Why this scored 45/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.