[PATCH 04/16] Bluetooth: 6lowpan: use l2cap_chan_close_unlocked()
From: Pauli Virtanen
Date: Sat Aug 29 2026 - 10:23:17 EST
6lowpan.c is using l2cap_chan_close() without taking chan->conn->lock,
so it may modify conn->chan_l without holding the guarding lock.
Fix the locking by using the l2cap_chan_close_unlocked() helper that
acquires the necessary locks.
Fixes: 15f32cabf426 ("Bluetooth: 6lowpan: add missing l2cap_chan_lock()")
Link: https://syzkaller.appspot.com/bug?extid=0e4ebcc970728e056324
Signed-off-by: Pauli Virtanen <pav@xxxxxx>
---
net/bluetooth/6lowpan.c | 27 +++++++++------------------
1 file changed, 9 insertions(+), 18 deletions(-)
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 30f4afa18bc8..4ea55950e599 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -921,9 +921,7 @@ static int bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type)
BT_DBG("peer %p chan %p", peer, peer->chan);
- l2cap_chan_lock(peer->chan);
- l2cap_chan_close(peer->chan, ENOENT);
- l2cap_chan_unlock(peer->chan);
+ l2cap_chan_close_unlocked(peer->chan, ENOENT);
return 0;
}
@@ -1025,9 +1023,9 @@ static void disconnect_all_peers(void)
struct lowpan_peer *peer;
int nchans;
- /* l2cap_chan_close() cannot be called from RCU, and lock ordering
- * chan->lock > devices_lock prevents taking write side lock, so copy
- * then close.
+ /* l2cap_chan_close_unlocked() cannot be called from RCU, and lock
+ * ordering chan->lock > devices_lock prevents taking write side lock,
+ * so copy then close.
*/
rcu_read_lock();
@@ -1062,9 +1060,7 @@ static void disconnect_all_peers(void)
spin_unlock(&devices_lock);
for (i = 0; i < nchans; ++i) {
- l2cap_chan_lock(chans[i]);
- l2cap_chan_close(chans[i], ENOENT);
- l2cap_chan_unlock(chans[i]);
+ l2cap_chan_close_unlocked(chans[i], ENOENT);
l2cap_chan_put(chans[i]);
}
} while (nchans);
@@ -1082,9 +1078,7 @@ static void do_enable_set(bool flag)
mutex_lock(&set_lock);
if (listen_chan) {
- l2cap_chan_lock(listen_chan);
- l2cap_chan_close(listen_chan, 0);
- l2cap_chan_unlock(listen_chan);
+ l2cap_chan_close_unlocked(listen_chan, 0);
l2cap_chan_put(listen_chan);
}
@@ -1132,9 +1126,7 @@ static ssize_t lowpan_control_write(struct file *fp,
mutex_lock(&set_lock);
if (listen_chan) {
- l2cap_chan_lock(listen_chan);
- l2cap_chan_close(listen_chan, 0);
- l2cap_chan_unlock(listen_chan);
+ l2cap_chan_close_unlocked(listen_chan, 0);
l2cap_chan_put(listen_chan);
listen_chan = NULL;
}
@@ -1303,10 +1295,9 @@ static void __exit bt_6lowpan_exit(void)
debugfs_remove(lowpan_control_debugfs);
if (listen_chan) {
- l2cap_chan_lock(listen_chan);
- l2cap_chan_close(listen_chan, 0);
- l2cap_chan_unlock(listen_chan);
+ l2cap_chan_close_unlocked(listen_chan, 0);
l2cap_chan_put(listen_chan);
+ listen_chan = NULL;
}
disconnect_devices();
--
2.55.0