summaryrefslogtreecommitdiff
path: root/tools/perf/scripts/python
diff options
context:
space:
mode:
authorAli Ahmet Memis <ali@iusegentoo.com>2026-08-07 00:59:55 +0000
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2026-08-07 15:40:28 -0400
commit9838a80096ba472d5e03057136a112631aabae6e (patch)
tree61bce129c9dd4470fe46ac29af2b30621fbf0811 /tools/perf/scripts/python
parent75722cde87ee24029e93e4e32d85309989f55991 (diff)
Bluetooth: ISO: do not force BT_LISTEN after a failed BIG sync
iso_sock_recvmsg() handles the deferred setup of a broadcast sink by dropping the socket lock, calling iso_conn_big_sync() and taking the lock again: release_sock(sk); iso_conn_big_sync(sk); lock_sock(sk); sk->sk_state = BT_LISTEN; The state is written unconditionally, but iso_conn_big_sync() returns void and has paths that do nothing at all: hci_get_route() may fail, and after re-acquiring the socket lock the connection may already be gone, in which case it bails out without ever issuing an LE BIG Create Sync. While the lock is dropped the connection can be torn down, for example when the controller reports HCI_EV_LE_PA_SYNC_LOST: hci_le_pa_sync_lost_evt() hci_disconn_cfm() -> iso_disconn_cfm() -> iso_conn_del() iso_chan_del() iso_pi(sk)->conn = NULL sk->sk_state = BT_CLOSED sock_set_flag(sk, SOCK_ZAPPED) iso_conn_big_sync() then finds conn == NULL and returns, but the caller still overwrites the BT_CLOSED that iso_chan_del() has just set. The socket ends up marked BT_LISTEN with no connection, so recvmsg() reports success for a setup that never happened and a later accept() waits for BIS connections that can never arrive instead of failing. A concurrent shutdown() reaches the same write by another route: __iso_sock_close() takes the BT_CONNECT2 PA sync path to iso_sock_disconn(), which sets BT_DISCONN but leaves conn and conn->hcon in place, so iso_conn_big_sync() succeeds and BT_LISTEN is written over BT_DISCONN. Both the BT_CONNECT2 and the BT_CONNECTED case write the state the same way. Let iso_conn_big_sync() report whether the BIG sync was started, and only move the socket to BT_LISTEN when it was and when the state has not changed while the lock was dropped, mirroring what the BT_CONNECT case of the same switch already does with iso_connect_cis(). Both conditions are needed, the error alone does not cover the shutdown() race. This corrupts the socket state machine only, it is not a memory safety issue. KASAN and lockdep stayed quiet in all of the runs below. Reproduced with an emulated controller over /dev/vhci on a KASAN + PROVE_LOCKING kernel. A PA sync broadcast sink socket is driven to BT_CONNECT2 and recvmsg() on it is raced against teardown, with a debug delay inside the lock-dropped section to widen the window: - HCI_EV_LE_PA_SYNC_LOST injected: 64 of 64 rounds left the socket in BT_LISTEN with the connection gone, recvmsg() returned 0 and accept() on that fd returned EAGAIN, which iso_sock_accept() can only do while the socket is BT_LISTEN. With this patch, 0 of 64, recvmsg() returns an error and accept() returns EBADFD. - shutdown() instead of a controller event: 24 of 32 rounds wedged in BT_LISTEN, 0 of 32 with this patch. With only the error check in place and a short window, one round still wedged while recvmsg() returned 0, which is the case the state re-check covers. An unraced control round behaves the same before and after: recvmsg() returns 0, the socket reaches BT_LISTEN and an LE BIG Create Sync is issued. Fixes: 7a17308c1788 ("Bluetooth: iso: Fix circular lock in iso_conn_big_sync") Cc: stable@vger.kernel.org Signed-off-by: Ali Ahmet Memis <ali@iusegentoo.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Diffstat (limited to 'tools/perf/scripts/python')
0 files changed, 0 insertions, 0 deletions