Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 1/2 5.10.y] Bluetooth: SCO: Fix UAF on sco_sock_timeout
@ 2026-08-04 21:44 Todd Kjos
  2026-08-04 21:44 ` [PATCH 2/2 5.10.y] Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing sock_hold Todd Kjos
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Todd Kjos @ 2026-08-04 21:44 UTC (permalink / raw)
  To: stable
  Cc: kernel-team, Lee Jones, Marcel Holtmann, Johan Hedberg,
	David S . Miller, Jakub Kicinski, linux-bluetooth, netdev,
	Luiz Augusto von Dentz, syzbot+4c0d0c4cde787116d465, Xiangyu Chen,
	He Zhe, Greg Kroah-Hartman, Todd Kjos

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

commit 1bf4470a3939c678fb822073e9ea77a0560bc6bb upstream.

conn->sk maybe have been unlinked/freed while waiting for sco_conn_lock
so this checks if the conn->sk is still valid by checking if it part of
sco_sk_list.

Reported-by: syzbot+4c0d0c4cde787116d465@syzkaller.appspotmail.com
Tested-by: syzbot+4c0d0c4cde787116d465@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=4c0d0c4cde787116d465
Fixes: ba316be1b6a0 ("Bluetooth: schedule SCO timeouts with delayed_work")
Change-Id: I0520456fb59dfdb11b0d8a4d6b7087684736a0ae
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
Signed-off-by: He Zhe <zhe.he@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[ Resolved trivial conflicts in net/bluetooth/sco.c ]
Signed-off-by: Todd Kjos <tkjos@google.com>
---
 include/net/bluetooth/bluetooth.h |  1 +
 net/bluetooth/af_bluetooth.c      | 22 ++++++++++++++++++++++
 net/bluetooth/sco.c               | 16 ++++++++++++----
 3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 43b4386018e26c41c914f87e050a0fe958700135..85bab90a6921ce1e9b9025647e23fafd97117ece 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -317,6 +317,7 @@ void bt_sock_link(struct bt_sock_list *l, struct sock *s);
 void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
 struct sock *bt_sock_alloc(struct net *net, struct socket *sock,
 			   struct proto *prot, int proto, gfp_t prio, int kern);
+bool bt_sock_linked(struct bt_sock_list *l, struct sock *s);
 int  bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 		     int flags);
 int  bt_sock_stream_recvmsg(struct socket *sock, struct msghdr *msg,
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index bef5b6330dd807504292671301c860b96c2ed18e..0af14e3318e7e02173970a1af8e183723bef2c50 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -184,6 +184,28 @@ void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
 }
 EXPORT_SYMBOL(bt_sock_unlink);
 
+bool bt_sock_linked(struct bt_sock_list *l, struct sock *s)
+{
+	struct sock *sk;
+
+	if (!l || !s)
+		return false;
+
+	read_lock(&l->lock);
+
+	sk_for_each(sk, &l->head) {
+		if (s == sk) {
+			read_unlock(&l->lock);
+			return true;
+		}
+	}
+
+	read_unlock(&l->lock);
+
+	return false;
+}
+EXPORT_SYMBOL(bt_sock_linked);
+
 void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh)
 {
 	const struct cred *old_cred;
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 01a01d6f01c309a6333859784261d97335dda413..8ac1f9a0222f3e947e75f37ac87115c74cbc0da9 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -76,6 +76,16 @@ struct sco_pinfo {
 #define SCO_CONN_TIMEOUT	(HZ * 40)
 #define SCO_DISCONN_TIMEOUT	(HZ * 2)
 
+static struct sock *sco_sock_hold(struct sco_conn *conn)
+{
+	if (!conn || !bt_sock_linked(&sco_sk_list, conn->sk))
+		return NULL;
+
+	sock_hold(conn->sk);
+
+	return conn->sk;
+}
+
 static void sco_sock_timeout(struct work_struct *work)
 {
 	struct sco_conn *conn = container_of(work, struct sco_conn,
@@ -87,9 +97,7 @@ static void sco_sock_timeout(struct work_struct *work)
 		sco_conn_unlock(conn);
 		return;
 	}
-	sk = conn->sk;
-	if (sk)
-		sock_hold(sk);
+	sk = sco_sock_hold(conn);
 	sco_conn_unlock(conn);
 
 	if (!sk)
@@ -192,7 +200,7 @@ static void sco_conn_del(struct hci_conn *hcon, int err)
 
 	/* Kill socket */
 	sco_conn_lock(conn);
-	sk = conn->sk;
+	sk = sco_sock_hold(conn);
 	sco_conn_unlock(conn);
 
 	if (sk) {
-- 
2.55.0.571.g244d577d93-goog


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

* [PATCH 2/2 5.10.y] Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing sock_hold
  2026-08-04 21:44 [PATCH 1/2 5.10.y] Bluetooth: SCO: Fix UAF on sco_sock_timeout Todd Kjos
@ 2026-08-04 21:44 ` Todd Kjos
  2026-08-04 22:09 ` [1/2,5.10.y] Bluetooth: SCO: Fix UAF on sco_sock_timeout bluez.test.bot
  2026-08-05  1:13 ` [PATCH 1/2 5.10.y] " Sasha Levin
  2 siblings, 0 replies; 5+ messages in thread
From: Todd Kjos @ 2026-08-04 21:44 UTC (permalink / raw)
  To: stable
  Cc: kernel-team, Lee Jones, Marcel Holtmann, Johan Hedberg,
	David S . Miller, Jakub Kicinski, linux-bluetooth, netdev,
	Hyunwoo Kim, Luiz Augusto von Dentz, Sasha Levin, Todd Kjos

From: Hyunwoo Kim <imv4bel@gmail.com>

[ Upstream commit 598dbba9919c5e36c54fe1709b557d64120cb94b ]

sco_recv_frame() reads conn->sk under sco_conn_lock() but immediately
releases the lock without holding a reference to the socket. A concurrent
close() can free the socket between the lock release and the subsequent
sk->sk_state access, resulting in a use-after-free.

Other functions in the same file (sco_sock_timeout(), sco_conn_del())
correctly use sco_sock_hold() to safely hold a reference under the lock.

Fix by using sco_sock_hold() to take a reference before releasing the
lock, and adding sock_put() on all exit paths.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Change-Id: Iae15e58c35bddb5b78a13f48f94dcb83f00ebb51
Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Todd Kjos <tkjos@google.com>
---
 net/bluetooth/sco.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 8ac1f9a0222f3e947e75f37ac87115c74cbc0da9..d2a9e851386b6897a9fa873cdae8f191e80d7fbf 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -313,7 +313,7 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
 	struct sock *sk;
 
 	sco_conn_lock(conn);
-	sk = conn->sk;
+	sk = sco_sock_hold(conn);
 	sco_conn_unlock(conn);
 
 	if (!sk)
@@ -322,11 +322,15 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
 	BT_DBG("sk %p len %d", sk, skb->len);
 
 	if (sk->sk_state != BT_CONNECTED)
-		goto drop;
+		goto drop_put;
 
-	if (!sock_queue_rcv_skb(sk, skb))
+	if (!sock_queue_rcv_skb(sk, skb)) {
+		sock_put(sk);
 		return;
+	}
 
+drop_put:
+	sock_put(sk);
 drop:
 	kfree_skb(skb);
 }
-- 
2.55.0.571.g244d577d93-goog


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

* RE: [1/2,5.10.y] Bluetooth: SCO: Fix UAF on sco_sock_timeout
  2026-08-04 21:44 [PATCH 1/2 5.10.y] Bluetooth: SCO: Fix UAF on sco_sock_timeout Todd Kjos
  2026-08-04 21:44 ` [PATCH 2/2 5.10.y] Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing sock_hold Todd Kjos
@ 2026-08-04 22:09 ` bluez.test.bot
  2026-08-05  1:13 ` [PATCH 1/2 5.10.y] " Sasha Levin
  2 siblings, 0 replies; 5+ messages in thread
From: bluez.test.bot @ 2026-08-04 22:09 UTC (permalink / raw)
  To: linux-bluetooth, tkjos

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

This is an automated email and please do not reply to this email.

Dear Submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.

----- Output -----

error: patch failed: include/net/bluetooth/bluetooth.h:317
error: include/net/bluetooth/bluetooth.h: patch does not apply
error: patch failed: net/bluetooth/af_bluetooth.c:184
error: net/bluetooth/af_bluetooth.c: patch does not apply
error: patch failed: net/bluetooth/sco.c:76
error: net/bluetooth/sco.c: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patch

Please resolve the issue and submit the patches again.


---
Regards,
Linux Bluetooth


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

* Re: [PATCH 1/2 5.10.y] Bluetooth: SCO: Fix UAF on sco_sock_timeout
  2026-08-04 21:44 [PATCH 1/2 5.10.y] Bluetooth: SCO: Fix UAF on sco_sock_timeout Todd Kjos
  2026-08-04 21:44 ` [PATCH 2/2 5.10.y] Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing sock_hold Todd Kjos
  2026-08-04 22:09 ` [1/2,5.10.y] Bluetooth: SCO: Fix UAF on sco_sock_timeout bluez.test.bot
@ 2026-08-05  1:13 ` Sasha Levin
  2026-08-05 19:16   ` Todd Kjos
  2 siblings, 1 reply; 5+ messages in thread
From: Sasha Levin @ 2026-08-05  1:13 UTC (permalink / raw)
  To: stable
  Cc: Sasha Levin, kernel-team, Lee Jones, Marcel Holtmann,
	Johan Hedberg, David S . Miller, Jakub Kicinski, linux-bluetooth,
	netdev, Luiz Augusto von Dentz, syzbot+4c0d0c4cde787116d465,
	Xiangyu Chen, He Zhe, Greg Kroah-Hartman, Todd Kjos

On Tue, Aug 04, 2026 at 09:44:05PM +0000, Todd Kjos wrote:
> @@ -192,7 +200,7 @@ static void sco_conn_del(struct hci_conn *hcon, int err)
>
>  	/* Kill socket */
>  	sco_conn_lock(conn);
> -	sk = conn->sk;
> +	sk = sco_sock_hold(conn);
>  	sco_conn_unlock(conn);
>
>  	if (sk) {

I think that this hunk leaks a struct sock reference on 5.10.

Unlike upstream and the 5.15/6.1 backports, where the sock_hold(sk) sits
just before sco_conn_unlock() and the upstream hunk deletes it, 5.10 keeps
its sock_hold(sk) inside the condition:

	sco_conn_lock(conn);
	sk = conn->sk;
	sco_conn_unlock(conn);

	if (sk) {
		sock_hold(sk);
		bh_lock_sock(sk);
		sco_sock_clear_timer(sk);
		sco_chan_del(sk, err);
		bh_unlock_sock(sk);
		sock_put(sk);
	}

So after this patch the function takes two references (one in
sco_sock_hold(), one from the surviving sock_hold(sk)) and drops only one.
That is a permanent struct sock leak on every SCO teardown, reachable by
any user with repeated connect/disconnect.

While respinning, please also drop the Change-Id: trailers from both
patches.

-- 
Thanks,
Sasha

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

* Re: [PATCH 1/2 5.10.y] Bluetooth: SCO: Fix UAF on sco_sock_timeout
  2026-08-05  1:13 ` [PATCH 1/2 5.10.y] " Sasha Levin
@ 2026-08-05 19:16   ` Todd Kjos
  0 siblings, 0 replies; 5+ messages in thread
From: Todd Kjos @ 2026-08-05 19:16 UTC (permalink / raw)
  To: Sasha Levin
  Cc: stable, kernel-team, Lee Jones, Marcel Holtmann, Johan Hedberg,
	David S . Miller, Jakub Kicinski, linux-bluetooth, netdev,
	Luiz Augusto von Dentz, syzbot+4c0d0c4cde787116d465, Xiangyu Chen,
	He Zhe, Greg Kroah-Hartman

On Tue, Aug 4, 2026 at 6:13 PM Sasha Levin <sashal@kernel.org> wrote:
>
> On Tue, Aug 04, 2026 at 09:44:05PM +0000, Todd Kjos wrote:
> > @@ -192,7 +200,7 @@ static void sco_conn_del(struct hci_conn *hcon, int err)
> >
> >       /* Kill socket */
> >       sco_conn_lock(conn);
> > -     sk = conn->sk;
> > +     sk = sco_sock_hold(conn);
> >       sco_conn_unlock(conn);
> >
> >       if (sk) {
>
> I think that this hunk leaks a struct sock reference on 5.10.

Yes, you are right.

>
> Unlike upstream and the 5.15/6.1 backports, where the sock_hold(sk) sits
> just before sco_conn_unlock() and the upstream hunk deletes it, 5.10 keeps
> its sock_hold(sk) inside the condition:
>
>         sco_conn_lock(conn);
>         sk = conn->sk;
>         sco_conn_unlock(conn);
>
>         if (sk) {
>                 sock_hold(sk);

This reference is not needed in the new version, since in we take the
reference above.

>                 bh_lock_sock(sk);
>                 sco_sock_clear_timer(sk);
>                 sco_chan_del(sk, err);
>                 bh_unlock_sock(sk);
>                 sock_put(sk);
>         }
>
> So after this patch the function takes two references (one in
> sco_sock_hold(), one from the surviving sock_hold(sk)) and drops only one.
> That is a permanent struct sock leak on every SCO teardown, reachable by
> any user with repeated connect/disconnect.
>
> While respinning, please also drop the Change-Id: trailers from both
> patches.

Will do. Sorry about that.

>
> --
> Thanks,
> Sasha

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

end of thread, other threads:[~2026-08-05 19:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-04 21:44 [PATCH 1/2 5.10.y] Bluetooth: SCO: Fix UAF on sco_sock_timeout Todd Kjos
2026-08-04 21:44 ` [PATCH 2/2 5.10.y] Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing sock_hold Todd Kjos
2026-08-04 22:09 ` [1/2,5.10.y] Bluetooth: SCO: Fix UAF on sco_sock_timeout bluez.test.bot
2026-08-05  1:13 ` [PATCH 1/2 5.10.y] " Sasha Levin
2026-08-05 19:16   ` Todd Kjos

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