From d884e3db1c6edee7baba46e56bbe52754ae90346 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Fri, 8 Nov 2024 16:41:43 +0800 Subject: [PATCH] Bluetooth: L2CAP_BR: CID of data sending is invalid There is a corner case that the channel is in disconnecting status, due to there is a disconnect request dent from peer. At this time, the channel is status is `BT_L2CAP_CONNECTED`. But it has been removed from `conn->channels` by calling the function `l2cap_br_remove_tx_cid`. And the disconnect event is notified upper layer via the callback `ops->disconnected`. The thread of the callback context is blocked due to the the calling of `printk` in the callback function. Then the pending lower priority thread, sending the data in this l2cap channel, is activated. Then in the function `bt_l2cap_br_send_cb`, a NULL pointer will be got according to the given CID. And unexpected behavior happens when accessing a NULL pointer, since the invalid channel pointer is not checked in function `bt_l2cap_br_send_cb`. Check the channel pointer after function `bt_l2cap_br_lookup_tx_cid` called. If the channel pointer is invalid, return error code `-ESHUTDOWN` directly. Signed-off-by: Lyle Zhu --- subsys/bluetooth/host/classic/l2cap_br.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/classic/l2cap_br.c b/subsys/bluetooth/host/classic/l2cap_br.c index 44d56b8d72a074f..1f7bafaabcdd691 100644 --- a/subsys/bluetooth/host/classic/l2cap_br.c +++ b/subsys/bluetooth/host/classic/l2cap_br.c @@ -866,9 +866,16 @@ int bt_l2cap_br_send_cb(struct bt_conn *conn, uint16_t cid, struct net_buf *buf, bt_conn_tx_cb_t cb, void *user_data) { struct bt_l2cap_chan *ch = bt_l2cap_br_lookup_tx_cid(conn, cid); - struct bt_l2cap_br_chan *br_chan = CONTAINER_OF(ch, struct bt_l2cap_br_chan, chan); + struct bt_l2cap_br_chan *br_chan; struct bt_l2cap_hdr *hdr; + if (ch == NULL) { + LOG_WRN("CID %d is not found on conn %p", cid, conn); + return -ESHUTDOWN; + } + + br_chan = CONTAINER_OF(ch, struct bt_l2cap_br_chan, chan); + LOG_DBG("chan %p buf %p len %zu", br_chan, buf, buf->len); #if L2CAP_BR_RET_FC_ENABLE