Skip to content

Commit 9e62280

Browse files
committed
Bluetooth: hci_event: Fix UAF in hci_acl_create_conn_sync
This fixes the following UFA in hci_acl_create_conn_sync where a connection still pending is command submission (conn->state == BT_OPEN) maybe freed, also since this also can happen with the likes of hci_le_create_conn_sync fix it as well: BUG: KASAN: slab-use-after-free in hci_acl_create_conn_sync+0x5ef/0x790 net/bluetooth/hci_sync.c:6861 Write of size 2 at addr ffff88805ffcc038 by task kworker/u11:2/9541 CPU: 1 UID: 0 PID: 9541 Comm: kworker/u11:2 Not tainted 6.16.0-rc7 #3 PREEMPT(full) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 Workqueue: hci3 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:378 [inline] print_report+0xca/0x230 mm/kasan/report.c:480 kasan_report+0x118/0x150 mm/kasan/report.c:593 hci_acl_create_conn_sync+0x5ef/0x790 net/bluetooth/hci_sync.c:6861 hci_cmd_sync_work+0x210/0x3a0 net/bluetooth/hci_sync.c:332 process_one_work kernel/workqueue.c:3238 [inline] process_scheduled_works+0xae1/0x17b0 kernel/workqueue.c:3321 worker_thread+0x8a0/0xda0 kernel/workqueue.c:3402 kthread+0x70e/0x8a0 kernel/kthread.c:464 ret_from_fork+0x3fc/0x770 arch/x86/kernel/process.c:148 ret_from_fork_asm+0x1a/0x30 home/kwqcheii/source/fuzzing/kernel/kasan/linux-6.16-rc7/arch/x86/entry/entry_64.S:245 </TASK> Allocated by task 123736: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 poison_kmalloc_redzone mm/kasan/common.c:377 [inline] __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:394 kasan_kmalloc include/linux/kasan.h:260 [inline] __kmalloc_cache_noprof+0x230/0x3d0 mm/slub.c:4359 kmalloc_noprof include/linux/slab.h:905 [inline] kzalloc_noprof include/linux/slab.h:1039 [inline] __hci_conn_add+0x233/0x1b30 net/bluetooth/hci_conn.c:939 hci_conn_add_unset net/bluetooth/hci_conn.c:1051 [inline] hci_connect_acl+0x16c/0x4e0 net/bluetooth/hci_conn.c:1634 pair_device+0x418/0xa70 net/bluetooth/mgmt.c:3556 hci_mgmt_cmd+0x9c9/0xef0 net/bluetooth/hci_sock.c:1719 hci_sock_sendmsg+0x6ca/0xef0 net/bluetooth/hci_sock.c:1839 sock_sendmsg_nosec net/socket.c:712 [inline] __sock_sendmsg+0x219/0x270 net/socket.c:727 sock_write_iter+0x258/0x330 net/socket.c:1131 new_sync_write fs/read_write.c:593 [inline] vfs_write+0x54b/0xa90 fs/read_write.c:686 ksys_write+0x145/0x250 fs/read_write.c:738 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f Freed by task 103680: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 poison_slab_object mm/kasan/common.c:247 [inline] __kasan_slab_free+0x62/0x70 mm/kasan/common.c:264 kasan_slab_free include/linux/kasan.h:233 [inline] slab_free_hook mm/slub.c:2381 [inline] slab_free mm/slub.c:4643 [inline] kfree+0x18e/0x440 mm/slub.c:4842 device_release+0x9c/0x1c0 kobject_cleanup lib/kobject.c:689 [inline] kobject_release lib/kobject.c:720 [inline] kref_put include/linux/kref.h:65 [inline] kobject_put+0x22b/0x480 lib/kobject.c:737 hci_conn_cleanup net/bluetooth/hci_conn.c:175 [inline] hci_conn_del+0x8ff/0xcb0 net/bluetooth/hci_conn.c:1173 hci_conn_complete_evt+0x3c7/0x1040 net/bluetooth/hci_event.c:3199 hci_event_func net/bluetooth/hci_event.c:7477 [inline] hci_event_packet+0x7e0/0x1200 net/bluetooth/hci_event.c:7531 hci_rx_work+0x46a/0xe80 net/bluetooth/hci_core.c:4070 process_one_work kernel/workqueue.c:3238 [inline] process_scheduled_works+0xae1/0x17b0 kernel/workqueue.c:3321 worker_thread+0x8a0/0xda0 kernel/workqueue.c:3402 kthread+0x70e/0x8a0 kernel/kthread.c:464 ret_from_fork+0x3fc/0x770 arch/x86/kernel/process.c:148 ret_from_fork_asm+0x1a/0x30 home/kwqcheii/source/fuzzing/kernel/kasan/linux-6.16-rc7/arch/x86/entry/entry_64.S:245 Last potentially related work creation: kasan_save_stack+0x3e/0x60 mm/kasan/common.c:47 kasan_record_aux_stack+0xbd/0xd0 mm/kasan/generic.c:548 insert_work+0x3d/0x330 kernel/workqueue.c:2183 __queue_work+0xbd9/0xfe0 kernel/workqueue.c:2345 queue_delayed_work_on+0x18b/0x280 kernel/workqueue.c:2561 pairing_complete+0x1e7/0x2b0 net/bluetooth/mgmt.c:3451 pairing_complete_cb+0x1ac/0x230 net/bluetooth/mgmt.c:3487 hci_connect_cfm include/net/bluetooth/hci_core.h:2064 [inline] hci_conn_failed+0x24d/0x310 net/bluetooth/hci_conn.c:1275 hci_conn_complete_evt+0x3c7/0x1040 net/bluetooth/hci_event.c:3199 hci_event_func net/bluetooth/hci_event.c:7477 [inline] hci_event_packet+0x7e0/0x1200 net/bluetooth/hci_event.c:7531 hci_rx_work+0x46a/0xe80 net/bluetooth/hci_core.c:4070 process_one_work kernel/workqueue.c:3238 [inline] process_scheduled_works+0xae1/0x17b0 kernel/workqueue.c:3321 worker_thread+0x8a0/0xda0 kernel/workqueue.c:3402 kthread+0x70e/0x8a0 kernel/kthread.c:464 ret_from_fork+0x3fc/0x770 arch/x86/kernel/process.c:148 ret_from_fork_asm+0x1a/0x30 home/kwqcheii/source/fuzzing/kernel/kasan/linux-6.16-rc7/arch/x86/entry/entry_64.S:245 Fixes: aef2aa4 ("Bluetooth: hci_event: Fix creating hci_conn object on error status") Reported-by: Junvyyang, Tencent Zhuque Lab <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 2e12868 commit 9e62280

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,27 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
12451245
return NULL;
12461246
}
12471247

1248+
static inline struct hci_conn *hci_conn_hash_lookup_role(struct hci_dev *hdev,
1249+
__u8 type, __u8 role,
1250+
bdaddr_t *ba)
1251+
{
1252+
struct hci_conn_hash *h = &hdev->conn_hash;
1253+
struct hci_conn *c;
1254+
1255+
rcu_read_lock();
1256+
1257+
list_for_each_entry_rcu(c, &h->list, list) {
1258+
if (c->type == type && c->role == role && !bacmp(&c->dst, ba)) {
1259+
rcu_read_unlock();
1260+
return c;
1261+
}
1262+
}
1263+
1264+
rcu_read_unlock();
1265+
1266+
return NULL;
1267+
}
1268+
12481269
static inline struct hci_conn *hci_conn_hash_lookup_le(struct hci_dev *hdev,
12491270
bdaddr_t *ba,
12501271
__u8 ba_type)

net/bluetooth/hci_event.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3087,8 +3087,18 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
30873087

30883088
hci_dev_lock(hdev);
30893089

3090+
/* Check for existing connection:
3091+
*
3092+
* 1. If it doesn't exist then it must be receiver/slave role.
3093+
* 2. If it does exist confirm that it is connecting/BT_CONNECT in case
3094+
* of initiator/master role since there could be a collision where
3095+
* either side is attempting to connect or something like a fuzzing
3096+
* testing is trying to play tricks to destroy the hcon object before
3097+
* it even attempts to connect (e.g. hcon->state == BT_OPEN).
3098+
*/
30903099
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
3091-
if (!conn) {
3100+
if (!conn ||
3101+
(conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) {
30923102
/* In case of error status and there is no connection pending
30933103
* just unlock as there is nothing to cleanup.
30943104
*/
@@ -5638,8 +5648,18 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
56385648
*/
56395649
hci_dev_clear_flag(hdev, HCI_LE_ADV);
56405650

5641-
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
5642-
if (!conn) {
5651+
/* Check for existing connection:
5652+
*
5653+
* 1. If it doesn't exist then use the role to create a new object.
5654+
* 2. If it does exist confirm that it is connecting/BT_CONNECT in case
5655+
* of initiator/master role since there could be a collision where
5656+
* either side is attempting to connect or something like a fuzzing
5657+
* testing is trying to play tricks to destroy the hcon object before
5658+
* it even attempts to connect (e.g. hcon->state == BT_OPEN).
5659+
*/
5660+
conn = hci_conn_hash_lookup_role(hdev, LE_LINK, role, bdaddr);
5661+
if (!conn ||
5662+
(conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) {
56435663
/* In case of error status and there is no connection pending
56445664
* just unlock as there is nothing to cleanup.
56455665
*/

0 commit comments

Comments
 (0)