Skip to content

Commit 5a430ee

Browse files
joerchannashif
authored andcommitted
Bluetooth: host: Fix L2CAP sent callback on disconnected channel
When receiving the L2CAP sent callbacks the dynamic L2CAP channel may have been disconnected already. The user of the dynamic channel should have received the disconnected and released callbacks for this channel to release any resources for the data being sent, so simply ignoring this sent callback is enough. Fix sent callbacks by providing the CID to the callback instead of a pointer to potentially released memory, and lookup the CID to check that it is still valid. Signed-off-by: Joakim Andersson <[email protected]>
1 parent 79d575b commit 5a430ee

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

subsys/bluetooth/host/l2cap.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,9 +1661,16 @@ static void l2cap_chan_tx_resume(struct bt_l2cap_le_chan *ch)
16611661

16621662
static void l2cap_chan_sdu_sent(struct bt_conn *conn, void *user_data)
16631663
{
1664-
struct bt_l2cap_chan *chan = user_data;
1664+
uint16_t cid = POINTER_TO_UINT(user_data);
1665+
struct bt_l2cap_chan *chan;
16651666

1666-
BT_DBG("conn %p chan %p", conn, chan);
1667+
BT_DBG("conn %p CID 0x%04x", conn, cid);
1668+
1669+
chan = bt_l2cap_le_lookup_tx_cid(conn, cid);
1670+
if (!chan) {
1671+
/* Received SDU sent callback for disconnected channel */
1672+
return;
1673+
}
16671674

16681675
if (chan->ops->sent) {
16691676
chan->ops->sent(chan);
@@ -1674,9 +1681,16 @@ static void l2cap_chan_sdu_sent(struct bt_conn *conn, void *user_data)
16741681

16751682
static void l2cap_chan_seg_sent(struct bt_conn *conn, void *user_data)
16761683
{
1677-
struct bt_l2cap_chan *chan = user_data;
1684+
uint16_t cid = POINTER_TO_UINT(user_data);
1685+
struct bt_l2cap_chan *chan;
16781686

1679-
BT_DBG("conn %p chan %p", conn, chan);
1687+
BT_DBG("conn %p CID 0x%04x", conn, cid);
1688+
1689+
chan = bt_l2cap_le_lookup_tx_cid(conn, cid);
1690+
if (!chan) {
1691+
/* Received segment sent callback for disconnected channel */
1692+
return;
1693+
}
16801694

16811695
l2cap_chan_tx_resume(BT_L2CAP_LE_CHAN(chan));
16821696
}
@@ -1738,10 +1752,12 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch,
17381752
*/
17391753
if ((buf == seg || !buf->len) && ch->chan.ops->sent) {
17401754
err = bt_l2cap_send_cb(ch->chan.conn, ch->tx.cid, seg,
1741-
l2cap_chan_sdu_sent, &ch->chan);
1755+
l2cap_chan_sdu_sent,
1756+
UINT_TO_POINTER(ch->tx.cid));
17421757
} else {
17431758
err = bt_l2cap_send_cb(ch->chan.conn, ch->tx.cid, seg,
1744-
l2cap_chan_seg_sent, &ch->chan);
1759+
l2cap_chan_seg_sent,
1760+
UINT_TO_POINTER(ch->tx.cid));
17451761
}
17461762

17471763
if (err) {

0 commit comments

Comments
 (0)