Skip to content

Commit 1f88a3b

Browse files
Tronilcvinayak
authored andcommitted
Bluetooth: L2CAP: Fix leaking tx metadata
Fix l2cap error handling generally not properly disposing of tx buffers for enhanced channels; Any callbacks have to be called and the l2cap_tx_meta_data has to be freed Signed-off-by: Troels Nilsson <[email protected]> (cherry picked from commit f0032a3) Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent cb7beb7 commit 1f88a3b

File tree

1 file changed

+22
-5
lines changed

1 file changed

+22
-5
lines changed

subsys/bluetooth/host/l2cap.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,20 @@ static void free_tx_meta_data(struct l2cap_tx_meta_data *data)
9999

100100
static sys_slist_t servers;
101101

102+
static void l2cap_tx_buf_destroy(struct bt_conn *conn, struct net_buf *buf, int err)
103+
{
104+
struct l2cap_tx_meta_data *data = l2cap_tx_meta_data(buf);
105+
bt_conn_tx_cb_t cb = data->cb;
106+
void *cb_user_data = data->user_data;
107+
108+
free_tx_meta_data(data);
109+
net_buf_unref(buf);
110+
111+
/* Make sure to call associated callback, if any */
112+
if (cb) {
113+
cb(conn, cb_user_data, err);
114+
}
115+
}
102116
#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
103117

104118
/* L2CAP signalling channel specific context */
@@ -933,7 +947,7 @@ static void l2cap_chan_tx_process(struct k_work *work)
933947
*/
934948
k_work_schedule(&ch->tx_work, K_MSEC(CONFIG_BT_L2CAP_RESCHED_MS));
935949
} else {
936-
net_buf_unref(buf);
950+
l2cap_tx_buf_destroy(ch->chan.conn, buf, sent);
937951
}
938952
break;
939953
}
@@ -986,13 +1000,13 @@ static void l2cap_chan_destroy(struct bt_l2cap_chan *chan)
9861000
}
9871001

9881002
if (le_chan->tx_buf) {
989-
net_buf_unref(le_chan->tx_buf);
1003+
l2cap_tx_buf_destroy(chan->conn, le_chan->tx_buf, -ESHUTDOWN);
9901004
le_chan->tx_buf = NULL;
9911005
}
9921006

9931007
/* Remove buffers on the TX queue */
9941008
while ((buf = net_buf_get(&le_chan->tx_queue, K_NO_WAIT))) {
995-
net_buf_unref(buf);
1009+
l2cap_tx_buf_destroy(chan->conn, buf, -ESHUTDOWN);
9961010
}
9971011

9981012
/* Remove buffers on the RX queue */
@@ -1912,6 +1926,9 @@ static void l2cap_chan_sdu_sent(struct bt_conn *conn, void *user_data, int err)
19121926
chan = bt_l2cap_le_lookup_tx_cid(conn, cid);
19131927
if (!chan) {
19141928
/* Received SDU sent callback for disconnected channel */
1929+
if (cb) {
1930+
cb(conn, cb_user_data, -ESHUTDOWN);
1931+
}
19151932
return;
19161933
}
19171934

@@ -2259,13 +2276,13 @@ static void l2cap_chan_shutdown(struct bt_l2cap_chan *chan)
22592276

22602277
/* Cleanup outstanding request */
22612278
if (le_chan->tx_buf) {
2262-
net_buf_unref(le_chan->tx_buf);
2279+
l2cap_tx_buf_destroy(chan->conn, le_chan->tx_buf, -ESHUTDOWN);
22632280
le_chan->tx_buf = NULL;
22642281
}
22652282

22662283
/* Remove buffers on the TX queue */
22672284
while ((buf = net_buf_get(&le_chan->tx_queue, K_NO_WAIT))) {
2268-
net_buf_unref(buf);
2285+
l2cap_tx_buf_destroy(chan->conn, buf, -ESHUTDOWN);
22692286
}
22702287

22712288
/* Remove buffers on the RX queue */

0 commit comments

Comments
 (0)