mirror of
https://github.com/apache/nuttx.git
synced 2026-09-04 08:04:02 +00:00
bt_conn_send() splits an outgoing L2CAP PDU into HCI ACL fragments no
larger than g_btdev.le_mtu, the controller's HCI ACL data packet length.
The first fragment caps its length correctly:
len = remaining;
if (len > g_btdev.le_mtu)
{
len = g_btdev.le_mtu;
}
The continuation loop below uses '<' instead of '>', so a continuation
shorter than le_mtu has its length raised to le_mtu rather than left
alone. Both len and remaining are uint16_t, which turns a wrong length
into an underflow:
With le_mtu 251 and a 300-byte PDU, the first fragment takes 251 bytes
and leaves remaining == 49. The loop then raises len from 49 to 251, so
memcpy(bt_buf_extend(buf, len), ptr, len);
reads 202 bytes past the end of the source, and
remaining -= len;
evaluates 49 - 251 as a uint16_t, wrapping to 65334. On the next
iteration len is 65334, which is not less than le_mtu, so it survives
the cap. bt_buf_extend() carries only a DEBUGASSERT on tailroom, so
with assertions disabled it adds 65334 to buf->len and returns, and the
memcpy writes 64 KB into a pooled buffer sized for a few hundred bytes.
Only the last fragment of a multi-fragment PDU is normally shorter than
le_mtu, so the first fragmented transmission triggers it.
Signed-off-by: AlmAck <gluca86@gmail.com>
|
||
|---|---|---|
| .. | ||
| bt_atomic.h | ||
| bt_att.c | ||
| bt_att.h | ||
| bt_buf.c | ||
| bt_buf.h | ||
| bt_conn.c | ||
| bt_conn.h | ||
| bt_gatt.c | ||
| bt_hcicore.c | ||
| bt_hcicore.h | ||
| bt_ioctl.c | ||
| bt_ioctl.h | ||
| bt_keys.c | ||
| bt_keys.h | ||
| bt_l2cap.c | ||
| bt_l2cap.h | ||
| bt_netdev.c | ||
| bt_queue.c | ||
| bt_queue.h | ||
| bt_services.c | ||
| bt_smp.c | ||
| bt_smp.h | ||
| bt_uuid.c | ||
| CMakeLists.txt | ||
| Kconfig | ||
| Make.defs | ||