Skip to content

Commit 9a8ec9e

Browse files
committed
Bluetooth: SCO: Fix possible circular locking dependency on sco_connect_cfm
This attempts to fix the following trace: ====================================================== WARNING: possible circular locking dependency detected 6.3.0-rc2-g0b93eeba4454 #4703 Not tainted ------------------------------------------------------ kworker/u3:0/46 is trying to acquire lock: ffff888001fd9130 (sk_lock-AF_BLUETOOTH-BTPROTO_SCO){+.+.}-{0:0}, at: sco_connect_cfm+0x118/0x4a0 but task is already holding lock: ffffffff831e3340 (hci_cb_list_lock){+.+.}-{3:3}, at: hci_sync_conn_complete_evt+0x1ad/0x3d0 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 (hci_cb_list_lock){+.+.}-{3:3}: __mutex_lock+0x13b/0xcc0 hci_sync_conn_complete_evt+0x1ad/0x3d0 hci_event_packet+0x55c/0x7c0 hci_rx_work+0x34c/0xa00 process_one_work+0x575/0x910 worker_thread+0x89/0x6f0 kthread+0x14e/0x180 ret_from_fork+0x2b/0x50 -> #1 (&hdev->lock){+.+.}-{3:3}: __mutex_lock+0x13b/0xcc0 sco_sock_connect+0xfc/0x630 __sys_connect+0x197/0x1b0 __x64_sys_connect+0x37/0x50 do_syscall_64+0x42/0x90 entry_SYSCALL_64_after_hwframe+0x70/0xda -> #0 (sk_lock-AF_BLUETOOTH-BTPROTO_SCO){+.+.}-{0:0}: __lock_acquire+0x18cc/0x3740 lock_acquire+0x151/0x3a0 lock_sock_nested+0x32/0x80 sco_connect_cfm+0x118/0x4a0 hci_sync_conn_complete_evt+0x1e6/0x3d0 hci_event_packet+0x55c/0x7c0 hci_rx_work+0x34c/0xa00 process_one_work+0x575/0x910 worker_thread+0x89/0x6f0 kthread+0x14e/0x180 ret_from_fork+0x2b/0x50 other info that might help us debug this: Chain exists of: sk_lock-AF_BLUETOOTH-BTPROTO_SCO --> &hdev->lock --> hci_cb_list_lock Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(hci_cb_list_lock); lock(&hdev->lock); lock(hci_cb_list_lock); lock(sk_lock-AF_BLUETOOTH-BTPROTO_SCO); *** DEADLOCK *** 4 locks held by kworker/u3:0/46: #0: ffff8880028d1130 ((wq_completion)hci0#2){+.+.}-{0:0}, at: process_one_work+0x4c0/0x910 #1: ffff8880013dfde0 ((work_completion)(&hdev->rx_work)){+.+.}-{0:0}, at: process_one_work+0x4c0/0x910 #2: ffff8880025d8070 (&hdev->lock){+.+.}-{3:3}, at: hci_sync_conn_complete_evt+0xa6/0x3d0 #3: ffffffffb79e3340 (hci_cb_list_lock){+.+.}-{3:3}, at: hci_sync_conn_complete_evt+0x1ad/0x3d0 Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent b76abe4 commit 9a8ec9e

File tree

1 file changed

+40
-29
lines changed

1 file changed

+40
-29
lines changed

net/bluetooth/sco.c

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -235,41 +235,57 @@ static int sco_chan_add(struct sco_conn *conn, struct sock *sk,
235235
return err;
236236
}
237237

238-
static int sco_connect(struct hci_dev *hdev, struct sock *sk)
238+
static int sco_connect(struct sock *sk)
239239
{
240240
struct sco_conn *conn;
241241
struct hci_conn *hcon;
242+
struct hci_dev *hdev;
242243
int err, type;
243244

244245
BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst);
245246

247+
hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
248+
if (!hdev)
249+
return -EHOSTUNREACH;
250+
251+
hci_dev_lock(hdev);
252+
246253
if (lmp_esco_capable(hdev) && !disable_esco)
247254
type = ESCO_LINK;
248255
else
249256
type = SCO_LINK;
250257

251258
if (sco_pi(sk)->setting == BT_VOICE_TRANSPARENT &&
252-
(!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev)))
253-
return -EOPNOTSUPP;
259+
(!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev))) {
260+
err = -EOPNOTSUPP;
261+
goto unlock;
262+
}
254263

255264
hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
256265
sco_pi(sk)->setting, &sco_pi(sk)->codec);
257-
if (IS_ERR(hcon))
258-
return PTR_ERR(hcon);
266+
if (IS_ERR(hcon)) {
267+
err = PTR_ERR(hcon);
268+
goto unlock;
269+
}
270+
271+
hci_dev_unlock(hdev);
272+
hci_dev_put(hdev);
259273

260274
conn = sco_conn_add(hcon);
261275
if (!conn) {
262276
hci_conn_drop(hcon);
263277
return -ENOMEM;
264278
}
265279

266-
/* Update source addr of the socket */
267-
bacpy(&sco_pi(sk)->src, &hcon->src);
268-
269280
err = sco_chan_add(conn, sk, NULL);
270281
if (err)
271282
return err;
272283

284+
lock_sock(sk);
285+
286+
/* Update source addr of the socket */
287+
bacpy(&sco_pi(sk)->src, &hcon->src);
288+
273289
if (hcon->state == BT_CONNECTED) {
274290
sco_sock_clear_timer(sk);
275291
sk->sk_state = BT_CONNECTED;
@@ -278,6 +294,13 @@ static int sco_connect(struct hci_dev *hdev, struct sock *sk)
278294
sco_sock_set_timer(sk, sk->sk_sndtimeo);
279295
}
280296

297+
release_sock(sk);
298+
299+
return err;
300+
301+
unlock:
302+
hci_dev_unlock(hdev);
303+
hci_dev_put(hdev);
281304
return err;
282305
}
283306

@@ -565,7 +588,6 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
565588
{
566589
struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
567590
struct sock *sk = sock->sk;
568-
struct hci_dev *hdev;
569591
int err;
570592

571593
BT_DBG("sk %p", sk);
@@ -574,37 +596,26 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
574596
addr->sa_family != AF_BLUETOOTH)
575597
return -EINVAL;
576598

577-
lock_sock(sk);
578-
if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
579-
err = -EBADFD;
580-
goto done;
581-
}
599+
if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND)
600+
return -EBADFD;
582601

583-
if (sk->sk_type != SOCK_SEQPACKET) {
602+
if (sk->sk_type != SOCK_SEQPACKET)
584603
err = -EINVAL;
585-
goto done;
586-
}
587-
588-
hdev = hci_get_route(&sa->sco_bdaddr, &sco_pi(sk)->src, BDADDR_BREDR);
589-
if (!hdev) {
590-
err = -EHOSTUNREACH;
591-
goto done;
592-
}
593-
hci_dev_lock(hdev);
594604

605+
lock_sock(sk);
595606
/* Set destination address and psm */
596607
bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr);
608+
release_sock(sk);
597609

598-
err = sco_connect(hdev, sk);
599-
hci_dev_unlock(hdev);
600-
hci_dev_put(hdev);
610+
err = sco_connect(sk);
601611
if (err)
602-
goto done;
612+
return err;
613+
614+
lock_sock(sk);
603615

604616
err = bt_sock_wait_state(sk, BT_CONNECTED,
605617
sock_sndtimeo(sk, flags & O_NONBLOCK));
606618

607-
done:
608619
release_sock(sk);
609620
return err;
610621
}

0 commit comments

Comments
 (0)