Reading buffered ERTM data after ACL link loss can clear local busy and send a supervisory frame after l2cap_conn_del() has destroyed the HCI channel, which oopses on a NULL pointer in hci_send_acl(). The socket still owns its L2CAP channel, so its lifetime does not protect the underlying HCI channel. Require BT_CONNECTED before clearing local busy in recvmsg. The socket lock already held here serializes this check and send with teardown, which closes the socket before the HCI channel is destroyed. Continue to allow buffered data to be read after disconnection. AI assistance was used. Fixes: 61aa4f5b9f43 ("Bluetooth: Use the transmit state machine for busy state changes") Cc: stable@vger.kernel.org # needs adjustments for 5.15 Signed-off-by: Zhao Li --- No new W=1 GCC/Clang, sparse or smatch warnings. In QEMU/vhci with KASAN, the base kernel faulted in hci_send_acl() during busy-clear after the link was dropped, in two boots; the patched kernel ran 31 rounds that reached that state (RNR sent, slow reads, link loss) without a report. net/bluetooth/l2cap_sock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 7a2551ef7f50..e5c15c083c1a 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1332,7 +1332,8 @@ static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg, * available. This avoids resending large numbers of * frames. */ - if (test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state) && + if (sk->sk_state == BT_CONNECTED && + test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state) && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1) l2cap_chan_busy(pi->chan, 0); base-commit: 6b4b543fa18757297ac756a6fe6e64f506b7844a -- 2.56.0