From: Cen Zhang <zzzccc427@gmail.com>
To: marcel@holtmann.org, luiz.dentz@gmail.com
Cc: linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org,
baijiaju1990@gmail.com, jjzuming@gmail.com, zzzccc427@gmail.com
Subject: [PATCH] Bluetooth: 6lowpan: Drain RCU readers on registration failure
Date: Thu, 8 Oct 2026 12:11:35 +0800 [thread overview]
Message-ID: <pm-bluetooth-objects-candidate-0230-v4-fd2c82b141a5bc3c5841@gmail.com> (raw)
A lowpan_btle_dev is embedded in its net_device allocation and must
remain alive until readers of bt_6lowpan_devices have left their RCU
sections. setup_netdev() publishes it before registration, but its
error path only unlinks it before calling free_netdev().
If a second controller's registration fails while multicast is sent
on an existing 6LoWPAN interface, send_mcast_pkt() can already have
selected the new entry. It reads entry->netdev before checking which
interface owns it. An early failure, such as allocating the device's
name node, leaves NETREG_UNINITIALIZED, so free_netdev() releases the
storage immediately.
The following ordering frees the selected entry before the reader
loads its netdev field:
Adapter creation (controller B) Multicast on controller A
setup_netdev()
list_add_rcu()
rcu_read_lock()
select B's entry
lowpan_register_netdev() fails
list_del_rcu()
free_netdev()
read entry->netdev
rcu_read_unlock()
Removing the list node does not wait for that reader, and
devices_lock does not serialize the multicast reader. The subsequent
field load is a use-after-free, reported by KASAN in bt_xmit().
Wait for an RCU grace period after dropping devices_lock and before
free_netdev(). This keeps the failed adapter allocated until traversals
that could have selected it complete. The callback is already sleepable,
and the wait happens outside the list spinlock.
KASAN report as below:
==================================================================
BUG: KASAN: slab-use-after-free in bt_xmit+0x1d06/0x21e0
Read of size 8 at addr ffff88810ef45030 by task python3/556
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? bt_xmit+0x1d06/0x21e0
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? bt_xmit+0x1d06/0x21e0
kasan_report+0xe0/0x110
? bt_xmit+0x1d06/0x21e0
bt_xmit+0x1d06/0x21e0
? __pfx_bt_xmit+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? lock_acquire+0x17b/0x2f0
? srso_alias_return_thunk+0x5/0xfbef5
? lock_is_held_type+0x8f/0x100
? dev_hard_start_xmit+0x187/0x660
? __pfx_bt_xmit+0x10/0x10
dev_hard_start_xmit+0x187/0x660
sch_direct_xmit+0x153/0x850
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_sch_direct_xmit+0x10/0x10
? do_raw_spin_lock+0x130/0x270
? __pfx_do_raw_spin_lock+0x10/0x10
? lock_is_held_type+0x8f/0x100
__dev_queue_xmit+0x3111/0x3aa0
? srso_alias_return_thunk+0x5/0xfbef5
? look_up_lock_class+0x59/0x130
? register_lock_class+0x41/0x790
? __pfx___dev_queue_xmit+0x10/0x10
? __lock_acquire+0x466/0x2260
? find_held_lock+0x2b/0x80
? ___neigh_create+0x1690/0x2540
? __local_bh_enable_ip+0xa6/0x120
? srso_alias_return_thunk+0x5/0xfbef5
? lockdep_hardirqs_on_prepare+0xea/0x1a0
? srso_alias_return_thunk+0x5/0xfbef5
? lock_acquire+0x17b/0x2f0
? srso_alias_return_thunk+0x5/0xfbef5
? find_held_lock+0x2b/0x80
? ip6_finish_output2+0x8be/0x1840
? srso_alias_return_thunk+0x5/0xfbef5
? neigh_connected_output+0x39f/0x4e0
? srso_alias_return_thunk+0x5/0xfbef5
neigh_connected_output+0x33f/0x4e0
ip6_finish_output2+0x8be/0x1840
ip6_finish_output+0x424/0xd50
ip6_output+0x210/0x640
? __pfx_ip6_mr_output+0x10/0x10
ip6_local_out+0x193/0x1c0
ip6_send_skb+0xfb/0x3e0
udp_v6_send_skb+0x6e1/0x1180
udpv6_sendmsg+0x1f9b/0x2a00
? get_random_u32+0xaf/0x640
? __pfx_udpv6_sendmsg+0x10/0x10
? lock_release+0xc8/0x280
? srso_alias_return_thunk+0x5/0xfbef5
? lockdep_hardirqs_on_prepare+0xea/0x1a0
? srso_alias_return_thunk+0x5/0xfbef5
? trace_hardirqs_on+0x18/0x160
? srso_alias_return_thunk+0x5/0xfbef5
? __local_bh_enable_ip+0xa6/0x120
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_udpv6_sendmsg+0x10/0x10
? inet6_sendmsg+0xff/0x140
inet6_sendmsg+0xff/0x140
__sys_sendto+0x320/0x470
? __pfx___sys_sendto+0x10/0x10
? exc_page_fault+0x5c/0xc0
? srso_alias_return_thunk+0x5/0xfbef5
? lock_release+0xc8/0x280
? handle_mm_fault+0x12e/0x580
__x64_sys_sendto+0xe5/0x1c0
? lockdep_hardirqs_on_prepare+0xea/0x1a0
? srso_alias_return_thunk+0x5/0xfbef5
? trace_hardirqs_on+0x18/0x160
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Allocated by task 502:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kvmalloc_node_noprof+0x353/0x930
alloc_netdev_mqs+0xa0/0x1250
chan_ready_cb+0x198/0x1110
l2cap_recv_frame+0x6dc0/0x8830
l2cap_recv_acldata+0xe9f/0x10e0
hci_rx_work+0x5a6/0xf00
process_one_work+0x908/0x19c0
worker_thread+0x65c/0xe40
kthread+0x34f/0x460
ret_from_fork+0x659/0x940
ret_from_fork_asm+0x1a/0x30
Freed by task 502:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
free_netdev+0x6ca/0x8f0
chan_ready_cb+0xd91/0x1110
l2cap_recv_frame+0x6dc0/0x8830
l2cap_recv_acldata+0xe9f/0x10e0
hci_rx_work+0x5a6/0xf00
process_one_work+0x908/0x19c0
worker_thread+0x65c/0xe40
kthread+0x34f/0x460
ret_from_fork+0x659/0x940
ret_from_fork_asm+0x1a/0x30
The buggy address belongs to the object at ffff88810ef44000
which
belongs to the cache kmalloc-8k of size
8192
The buggy address is located 4144 bytes inside of
freed
8192-byte region [ffff88810ef44000,
ffff88810ef46000)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
pfn:0x10ef40
head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x200000000000040(head|node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000040 ffff888100043180 dead000000000100
dead000000000122
raw: 0000000000000000 0000000000020002 00000000f5000000
0000000000000000
head: 0200000000000040 ffff888100043180 dead000000000100
dead000000000122
head: 0000000000000000 0000000000020002 00000000f5000000
0000000000000000
head: 0200000000000003 fffffffffffffe01 00000000ffffffff
00000000ffffffff
head: ffff88810ef41a80 0000000000000000 00000000ffffffff
0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff88810ef44f00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88810ef44f80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff88810ef45000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff88810ef45080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88810ef45100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================
Disabling lock debugging due to kernel taint
Fixes: 5857d1dbae7d ("Bluetooth: 6lowpan: Fix possible race")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 836add41f5d16f1df81042cbf9ba9b927e883eb8..0f6a45509d71c20bd556ad987e05f2fa1b0ab26b 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -706,6 +706,7 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_btle_dev **dev)
spin_lock(&devices_lock);
list_del_rcu(&(*dev)->list);
spin_unlock(&devices_lock);
+ synchronize_rcu();
free_netdev(netdev);
goto out;
}
reply other threads:[~2026-10-08 4:11 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pm-bluetooth-objects-candidate-0230-v4-fd2c82b141a5bc3c5841@gmail.com \
--to=zzzccc427@gmail.com \
--cc=baijiaju1990@gmail.com \
--cc=jjzuming@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luiz.dentz@gmail.com \
--cc=marcel@holtmann.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®