This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch releases/13.0
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/releases/13.0 by this push:
     new 0a4eff53c4f wireless/bluetooth: fix inverted MTU cap in bt_conn_send()
0a4eff53c4f is described below

commit 0a4eff53c4facc3dd25c6b04a1b8335a2809bb1c
Author: AlmAck <[email protected]>
AuthorDate: Sat Aug 29 19:00:13 2026 +0200

    wireless/bluetooth: fix inverted MTU cap in bt_conn_send()
    
    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 <[email protected]>
---
 wireless/bluetooth/bt_conn.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/wireless/bluetooth/bt_conn.c b/wireless/bluetooth/bt_conn.c
index 4764527f5ff..752054dfc17 100644
--- a/wireless/bluetooth/bt_conn.c
+++ b/wireless/bluetooth/bt_conn.c
@@ -442,7 +442,7 @@ void bt_conn_send(FAR struct bt_conn_s *conn, FAR struct 
bt_buf_s *buf)
       buf = bt_l2cap_create_pdu(conn);
 
       len = remaining;
-      if (len < g_btdev.le_mtu)
+      if (len > g_btdev.le_mtu)
         {
           len = g_btdev.le_mtu;
         }

Reply via email to