Skip to content

Commit 77df9e9

Browse files
committed
Bluetooth: SCO: Fix UAF on sco_sock_timeout
jira LE-2177 cve CVE-2024-50125 Rebuild_History Non-Buildable kernel-5.14.0-503.19.1.el9_5 commit-author Luiz Augusto von Dentz <[email protected]> commit 1bf4470 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: [email protected] Tested-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=4c0d0c4cde787116d465 Fixes: ba316be ("Bluetooth: schedule SCO timeouts with delayed_work") Signed-off-by: Luiz Augusto von Dentz <[email protected]> (cherry picked from commit 1bf4470) Signed-off-by: Jonathan Maple <[email protected]>
1 parent 854dac1 commit 77df9e9

File tree

3 files changed

+35
-6
lines changed

3 files changed

+35
-6
lines changed

include/net/bluetooth/bluetooth.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ int bt_sock_register(int proto, const struct net_proto_family *ops);
399399
void bt_sock_unregister(int proto);
400400
void bt_sock_link(struct bt_sock_list *l, struct sock *s);
401401
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
402+
bool bt_sock_linked(struct bt_sock_list *l, struct sock *s);
402403
struct sock *bt_sock_alloc(struct net *net, struct socket *sock,
403404
struct proto *prot, int proto, gfp_t prio, int kern);
404405
int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,

net/bluetooth/af_bluetooth.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,28 @@ void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
185185
}
186186
EXPORT_SYMBOL(bt_sock_unlink);
187187

188+
bool bt_sock_linked(struct bt_sock_list *l, struct sock *s)
189+
{
190+
struct sock *sk;
191+
192+
if (!l || !s)
193+
return false;
194+
195+
read_lock(&l->lock);
196+
197+
sk_for_each(sk, &l->head) {
198+
if (s == sk) {
199+
read_unlock(&l->lock);
200+
return true;
201+
}
202+
}
203+
204+
read_unlock(&l->lock);
205+
206+
return false;
207+
}
208+
EXPORT_SYMBOL(bt_sock_linked);
209+
188210
void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh)
189211
{
190212
const struct cred *old_cred;

net/bluetooth/sco.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ struct sco_pinfo {
7676
#define SCO_CONN_TIMEOUT (HZ * 40)
7777
#define SCO_DISCONN_TIMEOUT (HZ * 2)
7878

79+
static struct sock *sco_sock_hold(struct sco_conn *conn)
80+
{
81+
if (!conn || !bt_sock_linked(&sco_sk_list, conn->sk))
82+
return NULL;
83+
84+
sock_hold(conn->sk);
85+
86+
return conn->sk;
87+
}
88+
7989
static void sco_sock_timeout(struct work_struct *work)
8090
{
8191
struct sco_conn *conn = container_of(work, struct sco_conn,
@@ -87,9 +97,7 @@ static void sco_sock_timeout(struct work_struct *work)
8797
sco_conn_unlock(conn);
8898
return;
8999
}
90-
sk = conn->sk;
91-
if (sk)
92-
sock_hold(sk);
100+
sk = sco_sock_hold(conn);
93101
sco_conn_unlock(conn);
94102

95103
if (!sk)
@@ -194,9 +202,7 @@ static void sco_conn_del(struct hci_conn *hcon, int err)
194202

195203
/* Kill socket */
196204
sco_conn_lock(conn);
197-
sk = conn->sk;
198-
if (sk)
199-
sock_hold(sk);
205+
sk = sco_sock_hold(conn);
200206
sco_conn_unlock(conn);
201207

202208
if (sk) {

0 commit comments

Comments
 (0)