| From 0ed0917f7baa352b3192fe0c08d9ec1f9502c695 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 2 Sep 2021 23:13:06 -0400 |
| Subject: Bluetooth: fix init and cleanup of sco_conn.timeout_work |
| |
| From: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> |
| |
| [ Upstream commit 49d8a5606428ca0962d09050a5af81461ff90fbb ] |
| |
| Before freeing struct sco_conn, all delayed timeout work should be |
| cancelled. Otherwise, sco_sock_timeout could potentially use the |
| sco_conn after it has been freed. |
| |
| Additionally, sco_conn.timeout_work should be initialized when the |
| connection is allocated, not when the channel is added. This is |
| because an sco_conn can create channels with multiple sockets over its |
| lifetime, which happens if sockets are released but the connection |
| isn't deleted. |
| |
| Fixes: ba316be1b6a0 ("Bluetooth: schedule SCO timeouts with delayed_work") |
| Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> |
| Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/bluetooth/sco.c | 9 ++++----- |
| 1 file changed, 4 insertions(+), 5 deletions(-) |
| |
| diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c |
| index cc5a1d2545679..2c616c1c62958 100644 |
| --- a/net/bluetooth/sco.c |
| +++ b/net/bluetooth/sco.c |
| @@ -133,6 +133,7 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon) |
| return NULL; |
| |
| spin_lock_init(&conn->lock); |
| + INIT_DELAYED_WORK(&conn->timeout_work, sco_sock_timeout); |
| |
| hcon->sco_data = conn; |
| conn->hcon = hcon; |
| @@ -196,11 +197,11 @@ static void sco_conn_del(struct hci_conn *hcon, int err) |
| sco_chan_del(sk, err); |
| bh_unlock_sock(sk); |
| sock_put(sk); |
| - |
| - /* Ensure no more work items will run before freeing conn. */ |
| - cancel_delayed_work_sync(&conn->timeout_work); |
| } |
| |
| + /* Ensure no more work items will run before freeing conn. */ |
| + cancel_delayed_work_sync(&conn->timeout_work); |
| + |
| hcon->sco_data = NULL; |
| kfree(conn); |
| } |
| @@ -213,8 +214,6 @@ static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, |
| sco_pi(sk)->conn = conn; |
| conn->sk = sk; |
| |
| - INIT_DELAYED_WORK(&conn->timeout_work, sco_sock_timeout); |
| - |
| if (parent) |
| bt_accept_enqueue(parent, sk, true); |
| } |
| -- |
| 2.33.0 |
| |