]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Bluetooth: ISO: avoid NULL deref of conn in iso_conn_big_sync()
authorMuhammad Bilal <meatuni001@gmail.com>
Sun, 21 Jun 2026 16:23:05 +0000 (21:23 +0500)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 6 Jul 2026 14:46:56 +0000 (10:46 -0400)
iso_conn_big_sync() drops the socket lock to call hci_get_route() and
then re-acquires it, but dereferences iso_pi(sk)->conn->hcon afterwards
without re-checking that conn is still valid.

While the lock is dropped, the connection can be torn down under the
same socket lock: iso_disconn_cfm() -> iso_conn_del() -> iso_chan_del()
sets iso_pi(sk)->conn to NULL (and the broadcast teardown path can also
clear conn->hcon on its own). When iso_conn_big_sync() re-acquires the
lock and reads conn->hcon, conn may be NULL, causing a NULL pointer
dereference (hcon is the first member of struct iso_conn).

This path is reached from iso_sock_recvmsg() for a PA-sync broadcast
sink socket (BT_SK_DEFER_SETUP | BT_SK_PA_SYNC), so the dropped-lock
window can race with connection teardown driven by controller events.

Re-validate iso_pi(sk)->conn and its hcon after re-acquiring the socket
lock and bail out if the connection went away, as already done in the
sibling iso_sock_rebind_bc().

Fixes: 7a17308c17880d ("Bluetooth: iso: Fix circular lock in iso_conn_big_sync")
Cc: stable@vger.kernel.org
Signed-off-by: Muhammad Bilal <meatuni001@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/iso.c

index 793a481d7066ad2f8bd8e4592e49df64f722609c..cd7c7c9ea4fc616f2941acf1c518e04c806ee6f3 100644 (file)
@@ -1590,6 +1590,7 @@ static void iso_conn_big_sync(struct sock *sk)
 {
        int err;
        struct hci_dev *hdev;
+       struct iso_conn *conn;
        bdaddr_t src, dst;
        u8 src_type;
 
@@ -1612,8 +1613,17 @@ static void iso_conn_big_sync(struct sock *sk)
        hci_dev_lock(hdev);
        lock_sock(sk);
 
+       /* The socket lock was dropped for hci_get_route(), so the connection
+        * may have been torn down meanwhile: iso_chan_del() clears conn and
+        * the broadcast teardown path can clear conn->hcon on its own. Check
+        * both before dereferencing conn->hcon.
+        */
+       conn = iso_pi(sk)->conn;
+       if (!conn || !conn->hcon)
+               goto unlock;
+
        if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
-               err = hci_conn_big_create_sync(hdev, iso_pi(sk)->conn->hcon,
+               err = hci_conn_big_create_sync(hdev, conn->hcon,
                                               &iso_pi(sk)->qos,
                                               iso_pi(sk)->sync_handle,
                                               iso_pi(sk)->bc_num_bis,
@@ -1622,6 +1632,7 @@ static void iso_conn_big_sync(struct sock *sk)
                        bt_dev_err(hdev, "hci_big_create_sync: %d", err);
        }
 
+unlock:
        release_sock(sk);
        hci_dev_unlock(hdev);
        hci_dev_put(hdev);