From nobody Thu Apr 2 20:25:29 2026 Received: from mail-pl1-f171.google.com (mail-pl1-f171.google.com [209.85.214.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8AB5391846 for ; Thu, 26 Mar 2026 15:35:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774539317; cv=none; b=jNo3gXU+VsKNHNq9DsJ6nJ6OFGdOLgYJzaHkbGehSFurgzMU3EH4NM528sM3LdBnWVVeJAajtd+eY94u+nQyy84ernUN+Z7XobZTM100xShYFl6yD5sHjHJX8QiX0kRBeufnEXN/3hPV9BtY1UyJryIcRCeUw4UazcNS+8SjPIg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774539317; c=relaxed/simple; bh=BU3/bi8XXGEJ6aWfklsHKijjuQtx8U5F3JpSHaTAAFY=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=A9Pr+zB9LmxxpEBpQeiY2CNic5AnBlrCxkaMiJ+RU6mY0ffNAFTUtbtw6gWqdh5FYKv1QMP4pjYv5iUtHOqHJj6jGXxQio9WXWEmbDARteUYl5XODkeE2BbKyMGKzZFFRU5tMRazzAkes+Df2iJoxbDz879mSDIojPIFhL+rr3Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hFWT3iEK; arc=none smtp.client-ip=209.85.214.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hFWT3iEK" Received: by mail-pl1-f171.google.com with SMTP id d9443c01a7336-2adff872068so4686105ad.1 for ; Thu, 26 Mar 2026 08:35:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774539313; x=1775144113; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=qO8m2hCpAjgFFeaqcLdz5CV6U4Vjw8+U1Z3T8Ed/CyQ=; b=hFWT3iEKBjrVwtCURuEEUsb91c0XlicaScn4kqkzVUhgWr8WdFpwOrThPu8a0DDB7V KS1pyxEn7yDUQqENvcmRR0rIU1ZUdlnMddTpGW9Gp6AovbK5f+AZhchSL2LyUpO+fbi6 NNvhYoB5x+/iU8hdLHMWV2QIedhEFkWGr7vq+z1nHNf8FlntlU6hhUmuo5msLoDbWSzT viyFBOkJ9rDrpDn733618dkQN2yJFz1phKG385+k3tq6cqRICI1bniLZLvbKPJHgqoqV SYCAtKa5t+guDpXmk1ZjC3abOb7pGM9MSHZsTHPsUATBWR9PW/YTAXb6DLpGBd++eyeb QsNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774539313; x=1775144113; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=qO8m2hCpAjgFFeaqcLdz5CV6U4Vjw8+U1Z3T8Ed/CyQ=; b=SoOXwc6wSZ0z0puz5E3ss3Pue+91F058zoNbgiGoNKe2XTlQzMnzseZa8+r4Vmd0xp 01Om0Dbd8bKGRvHi0MU/js2ZSXSp9hvKTlF+qUTVqe48cNwR2ffIyj686D8AS2sr2e5r oi4B1iacrZ9oXlj3VrbwjGq6Dtqan+lA5qaj782ESuR3HCE0tZO8nOYGDyy6jklqtC42 jS8BvkvSF1t9u+ssdtiEWCPaZxQDzSpWcMHSuQ0Pju9rhFGdi/8PXL+0LKm1tTLT5t3K P+Bx6FYMhnpdlSnXUGCx/OeXAC4lkobozOcwRYoDQFo1KUnkpDfVJO+GV5VqZvWrDb9r eSLQ== X-Forwarded-Encrypted: i=1; AJvYcCWNOMWr8iBiiduyIatQKsjZuLS1OxxFcF1Xr8ne7Ls86Z6cn7YQzYA+6Lmb5LTFbeICNAgN2SG2obpWQYw=@vger.kernel.org X-Gm-Message-State: AOJu0YzpvjQ5VBa1Eg+TqWaZ7K11KJ6iGdomQMmOfh3LDNBVyKom6tHI S6GkROTXHWoZ4+104pTI1VDPgrL/4BK04dJgK5tyI30bi0sDGtDfKIod X-Gm-Gg: ATEYQzwGml483hbheIsztYc4YFxAv/EfQZa6SKDkhhYcrDhLkIZE4Lifu8/p6i92a7g /C+YYe0rRzDc5U9ajwZhRDxOJ5dyAXEhqo+1TTUBhxrXnvXiFs1kr8kaltLISjQZixZ92JM83YR o0aHshtEcQ55VBWA5uwMtZAbJ4ZyPcWNyEd8MmzxKgdGAscDvapBZzePiPzkJT5fMfNv5RHxFPO LM2BfmLStTAI1X1rj9ZzXDYU3OIug4+llHs0PEg9a7gZwAXfR2f22rDlMJe0horuHW6ubkojb6e 1S2tqtQEp9WoCU06l9r9g+UVbXVmu2A49vNS9nvSrOAauZAu0LzqHDEJAL9AZeWz/fq/GWlDQlf VsDgbGpTM+mvMNU72dLtVV+LJzZGdT+G/FwqwInED+/ViKbdYyYPJzuJYvf95ngnv+t+IZrgaVX ZFZtZURE25ikQx9PrfhQ== X-Received: by 2002:a17:903:41c2:b0:2b0:6d33:e7c0 with SMTP id d9443c01a7336-2b0b099c8f1mr88181905ad.1.1774539312646; Thu, 26 Mar 2026 08:35:12 -0700 (PDT) Received: from localhost ([111.228.63.84]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b0bc87ebf1sm33713045ad.44.2026.03.26.08.34.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Mar 2026 08:35:12 -0700 (PDT) From: Cen Zhang To: marcel@holtmann.org, luiz.dentz@gmail.com Cc: linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org, baijiaju1990@gmail.com, Cen Zhang Subject: [PATCH v2] Bluetooth: SCO: fix race conditions in sco_sock_connect() Date: Thu, 26 Mar 2026 23:16:45 +0800 Message-Id: <20260326151645.27909-1-zzzccc427@gmail.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" sco_sock_connect() checks sk_state and sk_type without holding the socket lock. Two concurrent connect() syscalls on the same socket can both pass the check and enter sco_connect(), leading to use-after-free. The buggy scenario involves three participants and was confirmed with additional logging instrumentation: Thread A (connect): HCI disconnect: Thread B (connect): sco_sock_connect(sk) sco_sock_connect(sk) sk_state=3D=3DBT_OPEN sk_state=3D=3DBT_OPEN (pass, no lock) (pass, no lock) sco_connect(sk): sco_connect(sk): hci_dev_lock hci_dev_lock hci_connect_sco <- blocked -> hcon1 sco_conn_add->conn1 lock_sock(sk) sco_chan_add: conn1->sk =3D sk sk->conn =3D conn1 sk_state=3DBT_CONNECT release_sock hci_dev_unlock hci_dev_lock sco_conn_del: lock_sock(sk) sco_chan_del: sk->conn=3DNULL conn1->sk=3DNULL sk_state=3D BT_CLOSED SOCK_ZAPPED release_sock hci_dev_unlock (unblocked) hci_connect_sco -> hcon2 sco_conn_add -> conn2 lock_sock(sk) sco_chan_add: sk->conn=3Dconn2 sk_state=3D BT_CONNECT // zombie sk! release_sock hci_dev_unlock Thread B revives a BT_CLOSED + SOCK_ZAPPED socket back to BT_CONNECT. Subsequent cleanup triggers double sock_put() and use-after-free. Meanwhile conn1 is leaked as it was orphaned when sco_conn_del() cleared the association. Fix this by: - Moving lock_sock() before the sk_state/sk_type checks in sco_sock_connect() to serialize concurrent connect attempts - Fixing the sk_type !=3D SOCK_SEQPACKET check to actually return the error instead of just assigning it - Adding a state re-check in sco_connect() after lock_sock() to catch state changes during the window between the locks - Adding sco_pi(sk)->conn check in sco_chan_add() to prevent double-attach of a socket to multiple connections - Adding hci_conn_drop() on sco_chan_add failure to prevent HCI connection leaks Fixes: 9a8ec9e8ebb5 ("Bluetooth: SCO: Fix possible circular locking depende= ncy on sco_connect_cfm") Signed-off-by: Cen Zhang --- net/bluetooth/sco.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index e7db50165879..689788ad26a4 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -298,7 +298,7 @@ static int sco_chan_add(struct sco_conn *conn, struct s= ock *sk, int err =3D 0; =20 sco_conn_lock(conn); - if (conn->sk) + if (conn->sk || sco_pi(sk)->conn) err =3D -EBUSY; else __sco_chan_add(conn, sk, parent); @@ -353,9 +353,20 @@ static int sco_connect(struct sock *sk) =20 lock_sock(sk); =20 + /* Recheck state after reacquiring the socket lock, as another + * thread may have changed it (e.g., closed the socket). + */ + if (sk->sk_state !=3D BT_OPEN && sk->sk_state !=3D BT_BOUND) { + release_sock(sk); + hci_conn_drop(hcon); + err =3D -EBADFD; + goto unlock; + } + err =3D sco_chan_add(conn, sk, NULL); if (err) { release_sock(sk); + hci_conn_drop(hcon); goto unlock; } =20 @@ -652,13 +663,18 @@ static int sco_sock_connect(struct socket *sock, stru= ct sockaddr_unsized *addr, addr->sa_family !=3D AF_BLUETOOTH) return -EINVAL; =20 - if (sk->sk_state !=3D BT_OPEN && sk->sk_state !=3D BT_BOUND) + lock_sock(sk); + + if (sk->sk_state !=3D BT_OPEN && sk->sk_state !=3D BT_BOUND) { + release_sock(sk); return -EBADFD; + } =20 - if (sk->sk_type !=3D SOCK_SEQPACKET) - err =3D -EINVAL; + if (sk->sk_type !=3D SOCK_SEQPACKET) { + release_sock(sk); + return -EINVAL; + } =20 - lock_sock(sk); /* Set destination address and psm */ bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr); release_sock(sk); --=20 2.34.1