[PATCH net v1] Bluetooth: 6lowpan: add the device to the list after

From: Binbin Deng

Date: Tue Sep 29 2026 - 08:29:12 EST


KASAN reports a maybe wild-memory-access in chan_ready_cb() while it
walks bt_6lowpan_devices via lookup_dev(). setup_netdev() publishes the
new lowpan_btle_dev to bt_6lowpan_devices with list_add_rcu() before
calling lowpan_register_netdev(), and when registration fails the entry
is removed from the list without waiting for a grace period: during the
rollback of register_netdevice() the NETDEV_UNREGISTER handler
device_event() removes it with list_del(), the error path of
setup_netdev() removes it again with list_del_rcu(), and free_netdev()
frees the net_device immediately because registration never completed. A
reader inside rcu_read_lock() that already holds a pointer to the entry
keeps walking the list through the removed node and dereferences

Oops: general protection fault, probably for non-canonical address 0xfbd59c0000000021: 0000 [#1] SMP KASAN NOPTI
KASAN: maybe wild-memory-access in range [0xdead000000000108-0xdead00000000010f]
Call Trace:
<TASK>
? __pfx_chan_ready_cb+0x10/0x10
l2cap_recv_frame+0x5f4e/0x83c0
? _raw_spin_lock+0x7f/0xd0
? __pfx_l2cap_recv_frame+0x10/0x10
? __mutex_unlock_slowpath.isra.0+0x259/0x500
? __pfx___mutex_unlock_slowpath.isra.0+0x10/0x10
? kasan_save_track+0x14/0x30
? mutex_lock+0x81/0xe0
? __pfx_mutex_lock+0x10/0x10
? hci_event_packet+0x518/0xb20
l2cap_recv_acldata+0xa64/0xd40
? __pfx__raw_spin_lock_irqsave+0x10/0x10
? __pfx_l2cap_recv_acldata+0x10/0x10
hci_rx_work+0x4ca/0x730
process_one_work+0x633/0x1030
? assign_work+0x11d/0x370
worker_thread+0x45b/0xd10
? __pfx_worker_thread+0x10/0x10
? __pfx_worker_thread+0x10/0x10
kthread+0x2c6/0x3b0
? recalc_sigpending+0x15c/0x1e0
? __pfx_kthread+0x10/0x10
ret_from_fork+0x36e/0x5a0
? __pfx_ret_from_fork+0x10/0x10
? __switch_to+0x572/0xdd0
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1a/0x30
</TASK>

Fix by adding the device to bt_6lowpan_devices only after registration
succeeded, so an entry whose netdev is about to be freed is never
visible to the lockless readers.

Fixes: 90305829635d ("Bluetooth: 6lowpan: Converting rwlocks to use RCU")
Signed-off-by: Binbin Deng <18983559317@xxxxxxx>
---
net/bluetooth/6lowpan.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 30f4afa18bc8..1668fce253d9 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -695,21 +695,18 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_btle_dev **dev)
(*dev)->hdev = chan->conn->hcon->hdev;
INIT_LIST_HEAD(&(*dev)->peers);

- spin_lock(&devices_lock);
- INIT_LIST_HEAD(&(*dev)->list);
- list_add_rcu(&(*dev)->list, &bt_6lowpan_devices);
- spin_unlock(&devices_lock);
-
err = lowpan_register_netdev(netdev, LOWPAN_LLTYPE_BTLE);
if (err < 0) {
BT_INFO("register_netdev failed %d", err);
- spin_lock(&devices_lock);
- list_del_rcu(&(*dev)->list);
- spin_unlock(&devices_lock);
free_netdev(netdev);
goto out;
}

+ spin_lock(&devices_lock);
+ INIT_LIST_HEAD(&(*dev)->list);
+ list_add_rcu(&(*dev)->list, &bt_6lowpan_devices);
+ spin_unlock(&devices_lock);
+
BT_DBG("ifindex %d peer bdaddr %pMR type %d my addr %pMR type %d",
netdev->ifindex, &chan->dst, chan->dst_type,
&chan->src, chan->src_type);
--
2.43.0