mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: hci_conn: Initialize the device before hash insertion
@ 2026-10-24 15:27 Cen Zhang
  0 siblings, 0 replies; only message in thread
From: Cen Zhang @ 2026-10-24 15:27 UTC (permalink / raw)
  To: marcel, luiz.dentz
  Cc: linux-bluetooth, linux-kernel, baijiaju1990, jjzuming, zzzccc427

An hci_conn must have an initialized embedded device before an RCU
reader can acquire a reference to it. __hci_conn_add() instead adds
the connection to conn_hash before hci_conn_init_sysfs() calls
device_initialize(). Holding hdev->lock during creation does not
exclude hci_disconnect_all_sync(), which looks up the connection and
calls hci_conn_get() under RCU without that lock.

When a new incoming ACL request overlaps controller poweroff before
the connection is registered in sysfs, the separate event and request
workqueues can execute this sequence:

1. The event worker holds hdev->lock and publishes a new connection
   in __hci_conn_add(), before device_initialize().
2. The request worker finds that connection under RCU, calls
   hci_conn_get() and leaves its RCU read-side critical section.
3. The event worker runs hci_conn_init_sysfs(), sets BT_CONNECT in
   hci_conn_request_evt() and releases hdev->lock.
4. The request worker calls hci_abort_conn_sync(), which acquires
   hdev->lock and reaches hci_conn_failed(), hci_conn_del() and
   hci_conn_del_sysfs() to delete the pending connection.
5. After abort returns, the request worker calls hci_conn_put().

device_initialize() resets the kobject reference count to one,
discarding the walker's premature get. If no other device references
exist, deletion of the unregistered device drops that one reference
and bt_link_release() frees the hci_conn. The walker's trailing put
then accesses the freed kobject, as shown by the KASAN report below.
The RCU grace period in hci_conn_hash_del() cannot preserve the walker
after it has left its read-side critical section.

Initialize the device before hci_conn_hash_add() publishes the
connection. The existing RCU publication then makes the initialized
device visible to readers, so the walker takes a valid reference that
survives deletion until its matching put.

KASAN report as below:

    ==================================================================
    BUG: KASAN: slab-use-after-free in kobject_put+0x4f3/0x610
    Read of size 1 at addr ffff88811e6fcd2c by task kworker/u17:0/559

    Workqueue: hci0 hci_cmd_sync_work
    Call Trace:
     <TASK>
     dump_stack_lvl+0x93/0xd0
     print_report+0xce/0x630
     ? kobject_put+0x4f3/0x610
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __virt_addr_valid+0x20d/0x410
     ? kobject_put+0x4f3/0x610
     kasan_report+0xe0/0x110
     ? kobject_put+0x4f3/0x610
     ? hci_disconnect_all_sync.constprop.0+0xd8/0x520
     kobject_put+0x4f3/0x610
     ? hci_disconnect_all_sync.constprop.0+0xd8/0x520
     put_device+0x24/0x30
     hci_disconnect_all_sync.constprop.0+0x176/0x520
     ? hci_disconnect_all_sync.constprop.0+0xcd/0x520
     ? __pfx_hci_disconnect_all_sync.constprop.0+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     hci_set_powered_sync+0x48f/0x680
     ? __pfx_hci_set_powered_sync+0x10/0x10
     ? __pfx___mutex_unlock_slowpath+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_is_held_type+0x8f/0x100
     set_powered_sync+0xaa/0x150
     hci_cmd_sync_work+0x1b3/0x450
     ? srso_alias_return_thunk+0x5/0xfbef5
     process_one_work+0x908/0x19c0
     ? __pfx_process_one_work+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_is_held_type+0x8f/0x100
     ? srso_alias_return_thunk+0x5/0xfbef5
     worker_thread+0x65c/0xe40
     ? __pfx_worker_thread+0x10/0x10
     kthread+0x34f/0x460
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_kthread+0x10/0x10
     ret_from_fork+0x659/0x940
     ? __pfx_ret_from_fork+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __switch_to+0x74f/0xf80
     ? __pfx_kthread+0x10/0x10
     ret_from_fork_asm+0x1a/0x30
     </TASK>

    Allocated by task 561:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     __kasan_kmalloc+0xaa/0xb0
     __kmalloc_cache_noprof+0x251/0x610
     __hci_conn_add+0x10c/0x1f70
     hci_conn_add_unset+0x72/0x120
     hci_conn_request_evt+0xb2b/0xd40
     hci_event_packet+0x894/0xc70
     hci_rx_work+0x367/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 559:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     kasan_save_free_info+0x3b/0x60
     __kasan_slab_free+0x5f/0x80
     kfree+0x307/0x580
     bt_link_release+0x4a/0xb0
     device_release+0xd7/0x280
     kobject_put+0x1ad/0x610
     put_device+0x24/0x30
     hci_conn_del_sysfs+0x15d/0x190
     hci_conn_del+0x684/0x1100
     hci_abort_conn_sync+0x7d6/0xae0
     hci_disconnect_all_sync.constprop.0+0x164/0x520
     hci_set_powered_sync+0x48f/0x680
     set_powered_sync+0xaa/0x150
     hci_cmd_sync_work+0x1b3/0x450
     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 ffff88811e6fc000
                                                                which
                                belongs to the cache kmalloc-8k of size
                                8192
    The buggy address is located 3372 bytes inside of
                                                                freed
                                8192-byte region [ffff88811e6fc000,
                                ffff88811e6fe000)

    The buggy address belongs to the physical page:
        page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
    pfn:0x11e6f8
    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 dead000000000122
    0000000000000000
        raw: 0000000000000000 0000000000020002 00000000f5000000
    0000000000000000
        head: 0200000000000040 ffff888100043180 dead000000000122
    0000000000000000
        head: 0000000000000000 0000000000020002 00000000f5000000
    0000000000000000
        head: 0200000000000003 fffffffffffffe01 00000000ffffffff
    00000000ffffffff
        head: 0000000000000000 0000000000000000 00000000ffffffff
    0000000000000000
    page dumped because: kasan: bad access detected

    Memory state around the buggy address:
     ffff88811e6fcc00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
     ffff88811e6fcc80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    >ffff88811e6fcd00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                                      ^
     ffff88811e6fcd80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
     ffff88811e6fce00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    ==================================================================

Fixes: 94d9ba9f9888 ("Bluetooth: hci_sync: Fix UAF in hci_disconnect_all_sync")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b007f623b2ecc..439ecde8f4d71 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1160,6 +1160,9 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type,
 
 	hci_dev_hold(hdev);
 
+	/* Initialize the device before publishing it to RCU readers. */
+	hci_conn_init_sysfs(conn);
+
 	hci_conn_hash_add(hdev, conn);
 
 	/* The SCO and eSCO connections will only be notified when their
@@ -1171,7 +1174,6 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type,
 			hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
 	}
 
-	hci_conn_init_sysfs(conn);
 	return conn;
 }
 

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-24 15:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-24 15:27 [PATCH] Bluetooth: hci_conn: Initialize the device before hash insertion Cen Zhang

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®