Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: ISO: do not force BT_LISTEN after a failed BIG sync
@ 2026-08-07  0:59 Ali Ahmet Memis
  2026-08-07  4:15 ` bluez.test.bot
  2026-08-07 16:30 ` [PATCH] " patchwork-bot+bluetooth
  0 siblings, 2 replies; 3+ messages in thread
From: Ali Ahmet Memis @ 2026-08-07  0:59 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz
  Cc: linux-bluetooth, linux-kernel, stable

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>
---
 net/bluetooth/iso.c | 30 ++++++++++++++++++++++--------
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index e5b2168e8819..aa2ce78f56a2 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -1660,9 +1660,9 @@ static void iso_conn_defer_accept(struct hci_conn *conn)
 	hci_send_cmd(hdev, HCI_OP_LE_ACCEPT_CIS, sizeof(cp), &cp);
 }
 
-static void iso_conn_big_sync(struct sock *sk)
+static int iso_conn_big_sync(struct sock *sk)
 {
-	int err;
+	int err = 0;
 	struct hci_dev *hdev;
 	struct iso_conn *conn;
 	bdaddr_t src, dst;
@@ -1677,7 +1677,7 @@ static void iso_conn_big_sync(struct sock *sk)
 	hdev = hci_get_route(&dst, &src, src_type);
 
 	if (!hdev)
-		return;
+		return -EHOSTUNREACH;
 
 	/* hci_le_big_create_sync requires hdev lock to be held, since
 	 * it enqueues the HCI LE BIG Create Sync command via
@@ -1693,8 +1693,10 @@ static void iso_conn_big_sync(struct sock *sk)
 	 * both before dereferencing conn->hcon.
 	 */
 	conn = iso_pi(sk)->conn;
-	if (!conn || !conn->hcon)
+	if (!conn || !conn->hcon) {
+		err = -ENOTCONN;
 		goto unlock;
+	}
 
 	if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
 		err = hci_conn_big_create_sync(hdev, conn->hcon,
@@ -1710,6 +1712,8 @@ static void iso_conn_big_sync(struct sock *sk)
 	release_sock(sk);
 	hci_dev_unlock(hdev);
 	hci_dev_put(hdev);
+
+	return err;
 }
 
 static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
@@ -1734,10 +1738,19 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
 		case BT_CONNECT2:
 			if (test_bit(BT_SK_PA_SYNC, &pi->flags)) {
 				release_sock(sk);
-				iso_conn_big_sync(sk);
+				err = iso_conn_big_sync(sk);
 				lock_sock(sk);
 
-				sk->sk_state = BT_LISTEN;
+				/* The socket lock was dropped, so the
+				 * connection may have been torn down
+				 * meanwhile and iso_chan_del() may have
+				 * already moved the socket to BT_CLOSED.
+				 * Only move on to BT_LISTEN if the BIG sync
+				 * was actually started and nothing else has
+				 * changed the state.
+				 */
+				if (!err && sk->sk_state == BT_CONNECT2)
+					sk->sk_state = BT_LISTEN;
 			} else {
 				iso_conn_defer_accept(pi->conn->hcon);
 				sk->sk_state = BT_CONFIG;
@@ -1748,10 +1761,11 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
 		case BT_CONNECTED:
 			if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
 				release_sock(sk);
-				iso_conn_big_sync(sk);
+				err = iso_conn_big_sync(sk);
 				lock_sock(sk);
 
-				sk->sk_state = BT_LISTEN;
+				if (!err && sk->sk_state == BT_CONNECTED)
+					sk->sk_state = BT_LISTEN;
 				early_ret = true;
 			}
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* RE: Bluetooth: ISO: do not force BT_LISTEN after a failed BIG sync
  2026-08-07  0:59 [PATCH] Bluetooth: ISO: do not force BT_LISTEN after a failed BIG sync Ali Ahmet Memis
@ 2026-08-07  4:15 ` bluez.test.bot
  2026-08-07 16:30 ` [PATCH] " patchwork-bot+bluetooth
  1 sibling, 0 replies; 3+ messages in thread
From: bluez.test.bot @ 2026-08-07  4:15 UTC (permalink / raw)
  To: linux-bluetooth, ali

[-- Attachment #1: Type: text/plain, Size: 2158 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1141845

---Test result---

Test Summary:
CheckPatch                    PASS      0.74 seconds
VerifyFixes                   PASS      0.14 seconds
VerifySignedoff               PASS      0.13 seconds
GitLint                       FAIL      0.33 seconds
SubjectPrefix                 PASS      0.13 seconds
BuildKernel                   PASS      25.23 seconds
CheckAllWarning               PASS      27.57 seconds
CheckSparse                   PASS      29.54 seconds
BuildKernel32                 PASS      27.96 seconds
CheckKernelLLVM               SKIP      0.00 seconds
TestRunnerSetup               PASS      523.00 seconds
TestRunner_iso-tester         PASS      97.77 seconds
IncrementalBuild              PASS      27.27 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
Bluetooth: ISO: do not force BT_LISTEN after a failed BIG sync

7: B3 Line contains hard tab characters (\t): "	release_sock(sk);"
8: B3 Line contains hard tab characters (\t): "	iso_conn_big_sync(sk);"
9: B3 Line contains hard tab characters (\t): "	lock_sock(sk);"
11: B3 Line contains hard tab characters (\t): "	sk->sk_state = BT_LISTEN;"
21: B3 Line contains hard tab characters (\t): "	hci_le_pa_sync_lost_evt()"
22: B3 Line contains hard tab characters (\t): "	  hci_disconn_cfm() -> iso_disconn_cfm() -> iso_conn_del()"
23: B3 Line contains hard tab characters (\t): "	    iso_chan_del()"
24: B3 Line contains hard tab characters (\t): "	      iso_pi(sk)->conn = NULL"
25: B3 Line contains hard tab characters (\t): "	      sk->sk_state = BT_CLOSED"
26: B3 Line contains hard tab characters (\t): "	      sock_set_flag(sk, SOCK_ZAPPED)"
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found


https://github.com/bluez/bluetooth-next/pull/544

---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Bluetooth: ISO: do not force BT_LISTEN after a failed BIG sync
  2026-08-07  0:59 [PATCH] Bluetooth: ISO: do not force BT_LISTEN after a failed BIG sync Ali Ahmet Memis
  2026-08-07  4:15 ` bluez.test.bot
@ 2026-08-07 16:30 ` patchwork-bot+bluetooth
  1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+bluetooth @ 2026-08-07 16:30 UTC (permalink / raw)
  To: Ali Ahmet Memis; +Cc: marcel, luiz.dentz, linux-bluetooth, linux-kernel, stable

Hello:

This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Fri,  7 Aug 2026 00:59:55 +0000 you wrote:
> 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);
> 
> [...]

Here is the summary with links:
  - Bluetooth: ISO: do not force BT_LISTEN after a failed BIG sync
    https://git.kernel.org/bluetooth/bluetooth-next/c/e177adea1f98

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-07 16:30 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-07  0:59 [PATCH] Bluetooth: ISO: do not force BT_LISTEN after a failed BIG sync Ali Ahmet Memis
2026-08-07  4:15 ` bluez.test.bot
2026-08-07 16:30 ` [PATCH] " patchwork-bot+bluetooth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox