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

janc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git


The following commit(s) were added to refs/heads/master by this push:
     new cbb317260 nimble/host: Fix available packets counter leak
cbb317260 is described below

commit cbb3172609f31fc9f17df083bf278d4aef8cb105
Author: Szymon Janc <[email protected]>
AuthorDate: Wed Jul 30 15:22:36 2025 +0200

    nimble/host: Fix available packets counter leak
    
    Mark connection as disconnected as soon as HCI Disconnection Complete
    event is processed. At this point ACL handle is no longer valid and
    controller will ignore any ACL data sent to it. Since later GAP
    Disconnected event is not handled atomically it may lead to TX data
    on that handle and thus 'leaking' available packets count on host.
    
    This is especially possible when there is connection timoue while
    host is in the middle of data transmission (eg sending nitifications).
---
 nimble/host/src/ble_hs_conn_priv.h |  1 +
 nimble/host/src/ble_hs_hci.c       | 11 +++++++++++
 nimble/host/src/ble_hs_hci_evt.c   |  3 ++-
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/nimble/host/src/ble_hs_conn_priv.h 
b/nimble/host/src/ble_hs_conn_priv.h
index 31e831c87..2d23422f5 100644
--- a/nimble/host/src/ble_hs_conn_priv.h
+++ b/nimble/host/src/ble_hs_conn_priv.h
@@ -37,6 +37,7 @@ typedef uint8_t ble_hs_conn_flags_t;
 #define BLE_HS_CONN_F_MASTER        0x01
 #define BLE_HS_CONN_F_TERMINATING   0x02
 #define BLE_HS_CONN_F_TX_FRAG       0x04 /* Cur ACL packet partially txed. */
+#define BLE_HS_CONN_F_TERMINATED    0x08
 
 #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
 #define BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN_REM \
diff --git a/nimble/host/src/ble_hs_hci.c b/nimble/host/src/ble_hs_hci.c
index 2321b90cb..e3fe335f5 100644
--- a/nimble/host/src/ble_hs_hci.c
+++ b/nimble/host/src/ble_hs_hci.c
@@ -515,6 +515,17 @@ ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct 
os_mbuf **om)
 
     BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
 
+    /* conn may be already disconnected but GAP events were not yet
+     * processed and thus connection object is stil on list, just ignore it
+     * in such case as ACL handle is not valid anymore and conn object will
+     * be removed shortly.
+     */
+    if (conn->bhc_flags & BLE_HS_CONN_F_TERMINATED) {
+        os_mbuf_free_chain(*om);
+        *om = NULL;
+        return 0;
+    }
+
     txom = *om;
     *om = NULL;
 
diff --git a/nimble/host/src/ble_hs_hci_evt.c b/nimble/host/src/ble_hs_hci_evt.c
index 47430423b..55031fcd7 100644
--- a/nimble/host/src/ble_hs_hci_evt.c
+++ b/nimble/host/src/ble_hs_hci_evt.c
@@ -213,7 +213,7 @@ ble_hs_hci_evt_disconn_complete(uint8_t event_code, const 
void *data,
                                 unsigned int len)
 {
     const struct ble_hci_ev_disconn_cmp *ev = data;
-    const struct ble_hs_conn *conn;
+    struct ble_hs_conn *conn;
 
     if (len != sizeof(*ev)) {
         return BLE_HS_ECONTROLLER;
@@ -223,6 +223,7 @@ ble_hs_hci_evt_disconn_complete(uint8_t event_code, const 
void *data,
     conn = ble_hs_conn_find(le16toh(ev->conn_handle));
     if (conn != NULL) {
         ble_hs_hci_add_avail_pkts(conn->bhc_outstanding_pkts);
+        conn->bhc_flags |= BLE_HS_CONN_F_TERMINATED;
     }
     ble_hs_unlock();
 

Reply via email to