Re: [PATCH v3 0/6] Bluetooth: Fix SCO setup failures after an abandoned setup
From: Luiz Augusto von Dentz
Date: Fri Oct 09 2026 - 10:06:38 EST
Hi Hitalo,
On Thu, Oct 8, 2026 at 6:26 PM Hitalo Souza <enghitalo@xxxxxxxxx> wrote:
>
> Since commit a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for
> aborting connections"), closing a SCO socket while its setup is pending
> deletes the hci_conn, after a Create Connection Cancel that cannot
> cancel a synchronous connection. When a new socket connects right away,
> e.g. PipeWire recreating the HFP transport after a codec negotiation as
> in bluez/bluez#2562, the abandoned setup can still complete, and:
>
> 1. It is matched to the new connection by address, the controller then
> rejects the new connection's own setup, and the rejection handler
> fails the first link on the ACL, which is now the connected one,
> without disconnecting it (patch 1).
>
> 2. It is matched to the new connection before that connection's own
> setup was sent: Enhanced Setup Synchronous Connection goes through
> the cmd_sync queue, and any setup waits for the ACL to leave sniff
> mode. The setup is then sent anyway and rejected. This is the order
> of events in the report (patch 2).
>
> 3. Nothing takes it over, or it is a second link for a connection
> that is already up: the link stays up in the controller with no
> connection for it, and the controller rejects every further setup
> for the device until the ACL drops (patch 4).
>
> Patches 3 and 5 make links that complete for an aborted connection be
> disconnected in general, as Luiz suggested, not only SCO ones. Patch 3:
> a link (ACL, SCO/eSCO or LE) that completes while its connection is
> being aborted, which then refuses the handle since 16e3b6429159
> ("Bluetooth: hci_conn: Fix modifying handle while aborting") and, for
> LE, 181a42edddf5 ("Bluetooth: Make handle of hci_conn be unique").
> Patch 5: an incoming ACL connection aborted after it was accepted,
> which is deleted before its link completes. Patch 6 stops notifying
> the driver of the air mode of a SCO link that did not come up: with
> btusb, that notification and the one for the connection's deletion
> right after could stop the audio of another SCO connection. btusb can
> still do that when a SCO link that was up goes down while another one
> stays up; that is not changed here.
>
> In 1 and 2 the new connection keeps the link of the abandoned setup,
> with the parameters of that setup: the completion event does not say
> which setup it belongs to. Its Air_Mode would show a change between
> CVSD and transparent data, but the series does not act on it. An
> abandoned setup that fails after a new connection was made, in Command
> Status or in its completion event, is likewise applied to that
> connection. Before a13f316e90fd both happened in another way, as the
> next socket reused the pending hci_conn.
>
> If a controller answers the setup of a SCO_LINK connection (only SCO
> packet types allowed, e.g. with the disable_esco parameter of sco.c)
> with an eSCO link, that link was ignored, so the connect timed out and
> the link stayed up. Patch 4 now lets the connection take it, as an
> eSCO connection already takes a SCO link.
>
> Changes in v3:
> - Patch 4: a SCO_LINK connection takes an eSCO link that answers its
> setup, instead of the link being ignored and left up (Sashiko). T6
> now checks that the connection gets the link.
> - Patch 1: the commit message notes that a Command Status does not
> tell which setup failed, which the patch does not change (Sashiko).
> - Rebased on bluetooth-next 97a128698d9d, without conflicts.
> - Tests for BlueZ's sco-tester and l2cap-tester that abort a connection
> while its connection complete event is pending, as Luiz asked:
> https://lore.kernel.org/linux-bluetooth/20261008215756.2710812-1-enghitalo@xxxxxxxxx/
> - v2: https://lore.kernel.org/linux-bluetooth/20261008151238.2138665-1-enghitalo@xxxxxxxxx/
>
> Changes in v2:
> - New patch 3, following Luiz's review: disconnect any link that
> completes while its connection is being aborted, on Connection
> Complete, Synchronous Connection Complete and LE Connection Complete.
> It replaces the SCO-only handling of that case in v1's patch 3, and
> covers the ACL and LE cases Sashiko pointed out.
> - Patch 4 (v1's patch 3) uses the helper of patch 3, and also
> disconnects a second SCO link that completes with Connection Complete
> for a connection that is already up (Sashiko).
> - New patch 5: disconnect an ACL link that completes after its
> connection was aborted and deleted (an incoming connection).
> - New patch 6: notify the driver of the air mode only of a SCO link
> that came up (Sashiko).
> - The disable_esco case is described as what it is: a controller
> answering a SCO-only setup with an eSCO link.
> - New tests T5b, T7, T8 and T9.
> - v1: https://lore.kernel.org/linux-bluetooth/20261007154353.148223-1-enghitalo@xxxxxxxxx/
>
> Patch 2 relies on hci_enhanced_setup_sync() taking hdev->lock, since
> 024e05f73a4c ("Bluetooth: hci_conn: Lock parent access during enhanced
> SCO setup"); a backport to a kernel without that commit needs the lock
> taken around the new checks.
>
> Testing:
>
> - QEMU/KVM, bluetooth-next at 97a128698d9d and with each patch applied
> in turn, x86_64 defconfig + kvm_guest.config + BT=y, BT_HCIVHCI=y. A
> userspace program emulates the controller and the headset over
> hci_vhci; the controller allows one eSCO link per ACL and rejects
> further setups with 0x0a (0x12 in T1, as in the report), except in
> T5, where it allows a second one. Each case was run over Setup
> Synchronous Connection (L), Enhanced Setup Synchronous Connection (E)
> and Add SCO Connection (A, controller without eSCO):
>
> T0 connect, receive SCO data, close
> T1 close a socket with its setup pending, connect a new one; the
> first setup completes, then the new one is rejected
> T1b like T1, but the first setup completes before the new one is
> sent, which waits for the ACL to leave sniff mode
> T1c like T1b, but the new setup waits in the cmd_sync queue (E only)
> T2 close a socket with its setup pending, the setup completes
> afterwards, connect a new socket (cancel answered 0x0b and 0x02)
> T2b like T2, but the setup completes while the abort still waits in
> the cmd_sync queue
> T3 a setup rejected with 0x0d in Command Status
> T4 like T2, but the abandoned setup completes with 0x22
> T5 like T1, but the new setup completes too, with a second link
> T5b an incoming SCO connection is up, and a second SCO link to the
> device completes with Connection Complete (A only)
> T6 disable_esco set, and the emulated controller answers the
> SCO-only setup with an eSCO link (L and E): the connection gets
> the link, receives SCO data and disconnects it when closed
> T7 an ACL connect to another device is aborted while paging, and
> the page succeeds as Create Connection Cancel arrives (cancel
> answered 0x0b)
> T8 with an emulated LE-only controller: an L2CAP LE connect is
> aborted while LE Create Connection is pending, and the connection
> completes as LE Create Connection Cancel arrives (cancel answered
> 0x0c); also with the cancel succeeding in time, where nothing may
> be disconnected
> T9 an incoming ACL connection is aborted with MGMT_OP_DISCONNECT
> after it was accepted; Create Connection Cancel fails with 0x02,
> then the link completes
>
> In T1c the cmd_sync queue waits for a Read RSSI (from mgmt Get
> Connection Information) that the emulator leaves unanswered; in T2b
> it waits for an ACL connection to another device, whose Connection
> Complete the emulator holds as during a page.
>
> T1 T1b T1c T2 T2b T5 T5b T6 T7 T8 T9
> bluetooth-next FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL
> + patch 1 pass FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL
> + patches 1-2 pass (*) pass FAIL FAIL FAIL FAIL FAIL FAIL FAIL FAIL
> + patches 1-3 pass (*) pass FAIL pass FAIL FAIL FAIL pass pass FAIL
> + patches 1-4 pass pass pass pass pass pass pass pass pass pass FAIL
> + patches 1-5 pass pass pass pass pass pass pass pass pass pass pass
> + patches 1-6 pass pass pass pass pass pass pass pass pass pass pass
>
> T0, T3, T4 and the LE connect cancelled in time pass on every row.
>
> The results are the same on L, E and A, except (*): pass on L and E,
> FAIL on A, where the abandoned link is not taken over by a connection
> that has not started its setup, and stays up until patch 4.
>
> Without the series, the new socket gets EINVAL in T1 (the emulator
> rejects with 0x12) and EMLINK in T1b and T1c (its duplicate setup is
> rejected with 0x0a), the next connect gets EMLINK in T2 and T2b, and
> the second links in T5 and T5b and the ACL and LE links in T7, T8 and
> T9 are not disconnected (they stay up until the ACL drops, or for
> good); in T6 the connect times out and the link stays up. With it,
> the new sockets and the connection in T6 receive SCO data and no
> Create Connection Cancel is sent for SCO; the links that nothing
> takes over (T1b on A, T2, T2b, T7, T8, T9) and the second links in T5
> and T5b are disconnected as soon as they complete, and T4 and the LE
> connect cancelled in time send no Disconnect. No kernel warnings.
> Patch 6 is not covered here, as hci_vhci has no notify callback.
>
> - BlueZ testers (master 866b0b8 with the new tests) in the same VM, on
> the debug kernel below plus CRYPTO_USER_API_{HASH,SKCIPHER}, run
> twice: with the series sco-tester (31), l2cap-tester (113) and
> iso-tester (141) pass, and without it only the three new tests fail.
> mgmt-tester has 8 to 10 LL Privacy failures of 506 per run, with and
> without the series.
>
> - Real hardware, with v2 (v3 only changes what happens when a SCO_LINK
> connection gets an eSCO link, which does not occur there): a MediaTek
> MT7921 (USB 04ca:3802, legacy Setup Synchronous Connection because of
> HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN) with a Sony WF-1000XM6, on
> v7.1.13 with the series built as the bluetooth module (patch 2 needs
> one change there, as hci_enhanced_setup_sync() does not take
> hdev->lock in that version; the other functions touched are the same
> as in bluetooth-next). With PipeWire 1.6.8 the abandoned setups were
> first seen there: Create Connection Cancel was answered with Unknown
> Connection Identifier, and the setup still completed afterwards.
>
> A SCO socket was closed 150 ms into its setup and a new one connected
> 0.3 s or 2.5 s later, five times; each abandoned setup completed about
> 0.2 s after it started, before the new connect. Without the series the
> first abandoned link after each ACL connect (two in the run) was left
> up, and from then on the controller rejected every setup, plain
> connects included, with Unsupported LMP Parameter Value (0x20) until
> the ACL was dropped. With the series no Create Connection Cancel was
> sent, each abandoned link was disconnected as soon as it completed,
> and every new socket and the plain connects after them received SCO
> data. An abandoned setup that failed (the headset rejects CVSD with
> 0x20) caused no Disconnect. Between the groups PipeWire switched the
> headset from A2DP to HFP (mSBC) for a recording while I counted
> aloud: speech was recorded all three times, with and without the
> series. The cases of patches 1 and 2 did not occur there.
>
> - W=1 builds of net/bluetooth/ and drivers/bluetooth/, no warnings:
> GCC 16.2.1 x86_64 allmodconfig and i386 defconfig, LLVM 22.1.8 arm64
> defconfig, arm multi_v7_defconfig, riscv defconfig and powerpc
> ppc64_defconfig (big-endian), with BT, BT_HCIBTUSB{,_MTK,_QCOM} and
> BT_VIRTIO.
>
> - sparse v0.6.5-rc1 on the same directories: the same 16 reports with
> and without the series, none on the lines touched here.
>
> - With the series, the same tests on a kernel with PROVE_LOCKING,
> PROVE_RCU, KASAN, DEBUG_ATOMIC_SLEEP, DEBUG_LIST and
> DEBUG_OBJECTS{,_WORK,_TIMERS} enabled: all pass on the three paths
> and with the LE-only controller, with no lockdep, KASAN or
> debugobjects reports, also while the BlueZ testers ran.
>
> The patches, the commit messages, this letter and the test programs
> were prepared with an AI assistant (see the Assisted-by tags), which
> reproduced the report in the emulator and wrote and tested the fixes;
> the real-hardware runs were done on my laptop with my headset.
>
> Hitalo Souza (6):
> Bluetooth: hci_event: Don't fail a connected SCO link on setup errors
> Bluetooth: hci_conn: Don't set up a SCO link that is already up
> Bluetooth: hci_event: Disconnect links that complete while being
> aborted
> Bluetooth: Don't leave abandoned SCO links up in the controller
> Bluetooth: hci_event: Disconnect an ACL link that completes after its
> abort
> Bluetooth: hci_event: Notify the driver only of SCO links that came up
>
> net/bluetooth/hci_conn.c | 24 +++++++-
> net/bluetooth/hci_event.c | 124 ++++++++++++++++++++++++++++++++------
> net/bluetooth/hci_sync.c | 8 +++
> 3 files changed, 135 insertions(+), 21 deletions(-)
>
>
> base-commit: 97a128698d9dcacb9a15cdc5080718a644b12637
> --
> 2.55.0
Sashiko is flagging a few more problems:
https://sashiko.dev/#/patchset/20261008222616.2780570-1-enghitalo%40gmail.com
--
Luiz Augusto von Dentz