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();