@@ -626,7 +626,38 @@ static void iso_conn_defer_reject(struct hci_conn *conn)
hci_send_cmd(conn->hdev, HCI_OP_LE_REJECT_CIS, sizeof(cp), &cp);
}
-static void __iso_sock_close(struct sock *sk)
+static void iso_conn_del_hci_conn(struct iso_conn *conn, struct hci_conn **del)
+{
+ /* Lock ordering forbids taking hdev->lock, postpone hci_conn_del */
+ iso_conn_lock(conn);
+ if (conn->hcon) {
+ hci_conn_get(conn->hcon);
+ hci_dev_hold(conn->hcon->hdev);
+ *del = conn->hcon;
+ conn->hcon = NULL;
+ }
+ iso_conn_unlock(conn);
+}
+
+static void iso_conn_del_hci_conn_finish(struct hci_conn *hcon)
+{
+ struct hci_dev *hdev;
+
+ if (!hcon)
+ return;
+
+ hdev = hcon->hdev;
+ hci_dev_lock(hdev);
+ if (hci_conn_is_alive(hdev, hcon)) {
+ iso_conn_del(hcon, ECONNRESET);
+ hci_conn_del(hcon);
+ }
+ hci_dev_unlock(hdev);
+ hci_dev_put(hdev);
+ hci_conn_put(hcon);
+}
+
+static void __iso_sock_close(struct sock *sk, struct hci_conn **del_conn)
{
BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
@@ -659,11 +690,8 @@ static void __iso_sock_close(struct sock *sk)
* needs to be removed so just call hci_conn_del so the cleanup
* callback do what is needed.
*/
- if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags) &&
- iso_pi(sk)->conn->hcon) {
- hci_conn_del(iso_pi(sk)->conn->hcon);
- iso_pi(sk)->conn->hcon = NULL;
- }
+ if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
+ iso_conn_del_hci_conn(iso_pi(sk)->conn, del_conn);
iso_chan_del(sk, ECONNRESET);
break;
@@ -680,11 +708,14 @@ static void __iso_sock_close(struct sock *sk)
/* Must be called on unlocked socket. */
static void iso_sock_close(struct sock *sk)
{
+ struct hci_conn *del_conn = NULL;
+
iso_sock_clear_timer(sk);
lock_sock(sk);
- __iso_sock_close(sk);
+ __iso_sock_close(sk, &del_conn);
release_sock(sk);
iso_sock_kill(sk);
+ iso_conn_del_hci_conn_finish(del_conn);
}
static void iso_sock_init(struct sock *sk, struct sock *parent)
@@ -1418,6 +1449,7 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
static int iso_sock_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
+ struct hci_conn *del_conn = NULL;
int err = 0;
BT_DBG("sock %p, sk %p, how %d", sock, sk, how);
@@ -1447,7 +1479,7 @@ static int iso_sock_shutdown(struct socket *sock, int how)
}
iso_sock_clear_timer(sk);
- __iso_sock_close(sk);
+ __iso_sock_close(sk, &del_conn);
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
!(current->flags & PF_EXITING))
@@ -1457,6 +1489,8 @@ static int iso_sock_shutdown(struct socket *sock, int how)
release_sock(sk);
sock_put(sk);
+ iso_conn_del_hci_conn_finish(del_conn);
+
return err;
}
__iso_sock_close calls hci_conn_del without hci_dev_lock, which is invalid and results to use-after-free under suitable conditions. But the lock cannot be taken here because of lock ordering hci_dev_lock > lock_sock > iso_conn_lock. Instead, take hci_conn_get temporarily, and delete the connection after lock_sock is released later on, if it is still alive. Also do iso_conn_del, so that we don't leak the iso_conn. Log: ================================================================== hci_chan_list_flush:2769: hcon ffff8880356b9000 hci_le_remove_cig:952: hci0: handle 0x00 hci_dev_put:1487: hci0 orig refcnt 9 iso_chan_del:156: sk ffff888010918800, conn ffff888004daee00, err 104 iso_chan_del:156: sk ffff888010918800, conn 0000000000000000, err 103 BUG: KASAN: slab-use-after-free in iso_conn_del (net/bluetooth/iso.c:211) bluetooth Write of size 8 at addr ffff8880356b99f0 by task kworker/u5:1/1073 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work [bluetooth] Call Trace: <TASK> dump_stack_lvl (lib/dump_stack.c:108) print_report (mm/kasan/report.c:352 mm/kasan/report.c:462) ? __virt_addr_valid (./include/linux/mmzone.h:1901 ./include/linux/mmzone.h:1997 arch/x86/mm/physaddr.c:65) ? iso_conn_del (net/bluetooth/iso.c:211) bluetooth kasan_report (mm/kasan/report.c:574) ? iso_conn_del (net/bluetooth/iso.c:211) bluetooth iso_conn_del (net/bluetooth/iso.c:211) bluetooth hci_conn_hash_flush (./include/net/bluetooth/hci_core.h:1872 net/bluetooth/hci_conn.c:2576) bluetooth hci_dev_close_sync (net/bluetooth/hci_sync.c:5043) bluetooth ? __pfx_hci_dev_close_sync (net/bluetooth/hci_sync.c:4974) bluetooth hci_set_powered_sync (net/bluetooth/hci_sync.c:5433 net/bluetooth/hci_sync.c:5441) bluetooth ? __pfx_hci_set_powered_sync (net/bluetooth/hci_sync.c:5437) bluetooth ? set_powered_sync (net/bluetooth/mgmt.c:1369) bluetooth ? __pfx_set_powered_sync (net/bluetooth/mgmt.c:1367) bluetooth hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) bluetooth process_one_work (kernel/workqueue.c:2410) ? __pfx_process_one_work (kernel/workqueue.c:2300) ? __pfx_do_raw_spin_lock (kernel/locking/spinlock_debug.c:113) ? mark_held_locks (kernel/locking/lockdep.c:4240) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2553) ? __pfx_worker_thread (kernel/workqueue.c:2495) kthread (kernel/kthread.c:379) ? __pfx_kthread (kernel/kthread.c:332) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 2372: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_add (./include/linux/slab.h:559 ./include/linux/slab.h:680 net/bluetooth/hci_conn.c:1002) bluetooth hci_bind_cis (net/bluetooth/hci_conn.c:1920) bluetooth iso_connect_cis (net/bluetooth/iso.c:383) bluetooth iso_sock_connect (net/bluetooth/iso.c:890) bluetooth __sys_connect (./include/linux/file.h:44 net/socket.c:2021) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 2372: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3786 mm/slub.c:3799) device_release (drivers/base/core.c:2489) kobject_put (lib/kobject.c:683 lib/kobject.c:714 ./include/linux/kref.h:65 lib/kobject.c:731) __iso_sock_close (net/bluetooth/iso.c:665) bluetooth iso_sock_release (net/bluetooth/iso.c:686 net/bluetooth/iso.c:1473) bluetooth __sock_release (net/socket.c:654) sock_close (net/socket.c:1399) __fput (fs/file_table.c:322) task_work_run (kernel/task_work.c:180) exit_to_user_mode_prepare (./include/linux/resume_user_mode.h:49 kernel/entry/common.c:171 kernel/entry/common.c:204) syscall_exit_to_user_mode (kernel/entry/common.c:130 kernel/entry/common.c:299) do_syscall_64 (arch/x86/entry/common.c:87) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) The buggy address belongs to the object at ffff8880356b9000 which belongs to the cache kmalloc-4k of size 4096 The buggy address is located 2544 bytes inside of freed 4096-byte region [ffff8880356b9000, ffff8880356ba000) ================================================================== Fixes: ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type") Signed-off-by: Pauli Virtanen <pav@iki.fi> --- net/bluetooth/iso.c | 50 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-)