All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: 6LoWPAN: Serialize multicast sends with peer removal
@ 2026-10-08  4:27 Cen Zhang
  2026-10-08  8:07 ` bluez.test.bot
  0 siblings, 1 reply; 2+ messages in thread
From: Cen Zhang @ 2026-10-08  4:27 UTC (permalink / raw)
  To: marcel, luiz.dentz
  Cc: linux-bluetooth, linux-kernel, baijiaju1990, jjzuming, zzzccc427

A peer's channel must remain alive until send_mcast_pkt() finishes using
it. The multicast walk protects the lowpan_peer with RCU, but peer_del()
defers only the peer allocation. On disconnect, l2cap_chan_del() drops
the connection-list reference, chan_close_cb() removes the peer and drops
the original channel reference, and l2cap_conn_del() drops its temporary
reference. A ready channel can then be freed while multicast transmit
still holds the peer, causing send_pkt() to write chan->data after free.
Another peer can keep the interface up, so the last-peer shutdown does
not drain this transmission.

Hold devices_lock across the multicast walk and send_pkt() calls so that
peer removal cannot release the channel reference until the send finishes.
Use the bottom-half-safe variants for all devices_lock critical sections
because transmit runs in softirq context. This prevents transmit from
interrupting a process-context lock holder on the same CPU and deadlocking.
The LE send path uses atomic allocations and does not acquire the channel
or connection mutexes, preserving the existing lock order and teardown
sequence.

The reported access and release path were:

        [Thu Oct  1 11:52:32 2026] BUG: KASAN: slab-use-after-free in
    send_pkt+0x2c5/0x300
        [Thu Oct  1 11:52:32 2026] Write of size 8 at addr ffff88810be0f4a0
     by task python3/535
    [...]
    [Thu Oct  1 11:52:32 2026] Freed by task 502:
    [...]
    [Thu Oct  1 11:52:32 2026]  l2cap_chan_put+0x273/0x3a0
    [Thu Oct  1 11:52:32 2026]  l2cap_conn_del+0x36d/0x770
    [Thu Oct  1 11:52:32 2026]  l2cap_disconn_cfm+0x87/0xd0
    [Thu Oct  1 11:52:32 2026]  hci_disconn_complete_evt+0x319/0xa30
    [...]

Fixes: 90305829635d ("Bluetooth: 6lowpan: Converting rwlocks to use RCU")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 836add41f5..8732132c47 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -471,6 +471,11 @@
 	struct lowpan_btle_dev *entry;
 	int err = 0;
 
+	/*
+	 * Peer removal drops the channel reference, so RCU alone is not
+	 * enough.
+	 */
+	spin_lock_bh(&devices_lock);
 	rcu_read_lock();
 
 	list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
@@ -502,6 +507,7 @@
 	}
 
 	rcu_read_unlock();
+	spin_unlock_bh(&devices_lock);
 
 	return err;
 }
@@ -657,10 +663,10 @@
 
 	lowpan_iphc_uncompress_eui48_lladdr(&peer->peer_addr, peer->lladdr);
 
-	spin_lock(&devices_lock);
+	spin_lock_bh(&devices_lock);
 	INIT_LIST_HEAD(&peer->list);
 	peer_add(dev, peer);
-	spin_unlock(&devices_lock);
+	spin_unlock_bh(&devices_lock);
 
 	/* Notifying peers about us needs to be done without locks held */
 	if (new_netdev)
@@ -695,17 +701,17 @@
 	(*dev)->hdev = chan->conn->hcon->hdev;
 	INIT_LIST_HEAD(&(*dev)->peers);
 
-	spin_lock(&devices_lock);
+	spin_lock_bh(&devices_lock);
 	INIT_LIST_HEAD(&(*dev)->list);
 	list_add_rcu(&(*dev)->list, &bt_6lowpan_devices);
-	spin_unlock(&devices_lock);
+	spin_unlock_bh(&devices_lock);
 
 	err = lowpan_register_netdev(netdev, LOWPAN_LLTYPE_BTLE);
 	if (err < 0) {
 		BT_INFO("register_netdev failed %d", err);
-		spin_lock(&devices_lock);
+		spin_lock_bh(&devices_lock);
 		list_del_rcu(&(*dev)->list);
-		spin_unlock(&devices_lock);
+		spin_unlock_bh(&devices_lock);
 		free_netdev(netdev);
 		goto out;
 	}
@@ -788,7 +794,7 @@
 
 	BT_DBG("chan %p conn %p", chan, chan->conn);
 
-	spin_lock(&devices_lock);
+	spin_lock_bh(&devices_lock);
 
 	list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
 		dev = lowpan_btle_dev(entry->netdev);
@@ -808,7 +814,7 @@
 	}
 
 	if (!err && last && dev && !atomic_read(&dev->peer_count)) {
-		spin_unlock(&devices_lock);
+		spin_unlock_bh(&devices_lock);
 
 		cancel_delayed_work_sync(&dev->notify_peers);
 
@@ -817,7 +823,7 @@
 		INIT_WORK(&entry->delete_netdev, delete_netdev);
 		schedule_work(&entry->delete_netdev);
 	} else {
-		spin_unlock(&devices_lock);
+		spin_unlock_bh(&devices_lock);
 	}
 }
 
@@ -918,18 +924,18 @@
 
 	BT_DBG("conn %p dst type %u", conn, dst_type);
 
-	spin_lock(&devices_lock);
+	spin_lock_bh(&devices_lock);
 
 	peer = lookup_peer(conn);
 	if (!peer) {
-		spin_unlock(&devices_lock);
+		spin_unlock_bh(&devices_lock);
 		return -ENOENT;
 	}
 
 	chan = peer->chan;
 	l2cap_chan_hold(chan);
 
-	spin_unlock(&devices_lock);
+	spin_unlock_bh(&devices_lock);
 
 	BT_DBG("peer %p chan %p", peer, chan);
 
@@ -1053,7 +1059,7 @@
 
 		nchans = 0;
 
-		spin_lock(&devices_lock);
+		spin_lock_bh(&devices_lock);
 
 		list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
 			list_for_each_entry_rcu(peer, &entry->peers, list) {
@@ -1070,7 +1076,7 @@
 		}
 
 done:
-		spin_unlock(&devices_lock);
+		spin_unlock_bh(&devices_lock);
 
 		for (i = 0; i < nchans; ++i) {
 			l2cap_chan_close_unlocked(chans[i], ENOENT);
@@ -1195,7 +1201,7 @@
 	struct lowpan_btle_dev *entry;
 	struct lowpan_peer *peer;
 
-	spin_lock(&devices_lock);
+	spin_lock_bh(&devices_lock);
 
 	list_for_each_entry(entry, &bt_6lowpan_devices, list) {
 		list_for_each_entry(peer, &entry->peers, list)
@@ -1203,7 +1209,7 @@
 				   &peer->chan->dst, peer->chan->dst_type);
 	}
 
-	spin_unlock(&devices_lock);
+	spin_unlock_bh(&devices_lock);
 
 	return 0;
 }
@@ -1269,7 +1275,7 @@
 
 	switch (event) {
 	case NETDEV_UNREGISTER:
-		spin_lock(&devices_lock);
+		spin_lock_bh(&devices_lock);
 		list_for_each_entry(entry, &bt_6lowpan_devices, list) {
 			if (entry->netdev == netdev) {
 				BT_DBG("Unregistered netdev %s %p",
@@ -1278,7 +1284,7 @@
 				break;
 			}
 		}
-		spin_unlock(&devices_lock);
+		spin_unlock_bh(&devices_lock);
 		break;
 	}
 

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* RE: Bluetooth: 6LoWPAN: Serialize multicast sends with peer removal
  2026-10-08  4:27 [PATCH] Bluetooth: 6LoWPAN: Serialize multicast sends with peer removal Cen Zhang
@ 2026-10-08  8:07 ` bluez.test.bot
  0 siblings, 0 replies; 2+ messages in thread
From: bluez.test.bot @ 2026-10-08  8:07 UTC (permalink / raw)
  To: linux-bluetooth, zzzccc427

[-- Attachment #1: Type: text/plain, Size: 1072 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1181249/

---Test result---

Test Summary:
CheckPatch                    PASS      1.66 seconds
VerifyFixes                   PASS      0.09 seconds
VerifySignedoff               PASS      0.08 seconds
GitLint                       PASS      0.23 seconds
SubjectPrefix                 PASS      0.07 seconds
BuildKernel                   PASS      28.96 seconds
CheckAllWarning               PASS      32.92 seconds
CheckSparse                   PASS      35.69 seconds
BuildKernel32                 PASS      28.86 seconds
CheckKernelLLVM               PASS      32.44 seconds
TestRunnerSetup               PASS      774.46 seconds
TestRunner_6lowpan-tester     PASS      5.51 seconds
IncrementalBuild              PASS      27.25 seconds



https://github.com/bluez/bluetooth-next/pull/881

---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-08  8:07 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-08  4:27 [PATCH] Bluetooth: 6LoWPAN: Serialize multicast sends with peer removal Cen Zhang
2026-10-08  8:07 ` bluez.test.bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.