|
Takashi Iwai |
ce744d |
From 1d80d57ffcb55488f0ec0b77928d4f82d16b6a90 Mon Sep 17 00:00:00 2001
|
|
Takashi Iwai |
ce744d |
From: Ying Hsu <yinghsu@chromium.org>
|
|
Takashi Iwai |
ce744d |
Date: Wed, 11 Jan 2023 03:16:14 +0000
|
|
Takashi Iwai |
ce744d |
Subject: [PATCH] Bluetooth: Fix possible deadlock in rfcomm_sk_state_change
|
|
Takashi Iwai |
ce744d |
Git-commit: 1d80d57ffcb55488f0ec0b77928d4f82d16b6a90
|
|
Takashi Iwai |
ce744d |
Patch-mainline: v6.2-rc5
|
|
Takashi Iwai |
ce744d |
References: git-fixes
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
syzbot reports a possible deadlock in rfcomm_sk_state_change [1].
|
|
Takashi Iwai |
ce744d |
While rfcomm_sock_connect acquires the sk lock and waits for
|
|
Takashi Iwai |
ce744d |
the rfcomm lock, rfcomm_sock_release could have the rfcomm
|
|
Takashi Iwai |
ce744d |
lock and hit a deadlock for acquiring the sk lock.
|
|
Takashi Iwai |
ce744d |
Here's a simplified flow:
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
Rfcomm_sock_connect: lock_sock(sk) rfcomm_dlc_open: rfcomm_lock()
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
Rfcomm_sock_release: rfcomm_sock_shutdown: rfcomm_lock() __rfcomm_dlc_close: rfcomm_k_state_change: lock_sock(sk)
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
This patch drops the sk lock before calling rfcomm_dlc_open to
|
|
Takashi Iwai |
ce744d |
avoid the possible deadlock and holds sk's reference count to
|
|
Takashi Iwai |
ce744d |
prevent use-after-free after rfcomm_dlc_open completes.
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
Reported-by: syzbot+d7ce59...@syzkaller.appspotmail.com
|
|
Takashi Iwai |
ce744d |
Fixes: 1804fdf6e494 ("Bluetooth: btintel: Combine setting up MSFT extension")
|
|
Takashi Iwai |
ce744d |
Link: https://syzkaller.appspot.com/bug?extid=d7ce59b06b3eb14fd218 [1]
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
Signed-off-by: Ying Hsu <yinghsu@chromium.org>
|
|
Takashi Iwai |
ce744d |
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
|
|
Takashi Iwai |
ce744d |
Acked-by: Takashi Iwai <tiwai@suse.de>
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
---
|
|
Takashi Iwai |
ce744d |
net/bluetooth/rfcomm/sock.c | 7 ++++++-
|
|
Takashi Iwai |
ce744d |
1 file changed, 6 insertions(+), 1 deletion(-)
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
|
|
Takashi Iwai |
ce744d |
index 21e24da4847f..4397e14ff560 100644
|
|
Takashi Iwai |
ce744d |
--- a/net/bluetooth/rfcomm/sock.c
|
|
Takashi Iwai |
ce744d |
+++ b/net/bluetooth/rfcomm/sock.c
|
|
Takashi Iwai |
ce744d |
@@ -391,6 +391,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
|
|
Takashi Iwai |
ce744d |
addr->sa_family != AF_BLUETOOTH)
|
|
Takashi Iwai |
ce744d |
return -EINVAL;
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
+ sock_hold(sk);
|
|
Takashi Iwai |
ce744d |
lock_sock(sk);
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
|
|
Takashi Iwai |
ce744d |
@@ -410,14 +411,18 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
|
|
Takashi Iwai |
ce744d |
d->sec_level = rfcomm_pi(sk)->sec_level;
|
|
Takashi Iwai |
ce744d |
d->role_switch = rfcomm_pi(sk)->role_switch;
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
+ /* Drop sock lock to avoid potential deadlock with the RFCOMM lock */
|
|
Takashi Iwai |
ce744d |
+ release_sock(sk);
|
|
Takashi Iwai |
ce744d |
err = rfcomm_dlc_open(d, &rfcomm_pi(sk)->src, &sa->rc_bdaddr,
|
|
Takashi Iwai |
ce744d |
sa->rc_channel);
|
|
Takashi Iwai |
ce744d |
- if (!err)
|
|
Takashi Iwai |
ce744d |
+ lock_sock(sk);
|
|
Takashi Iwai |
ce744d |
+ if (!err && !sock_flag(sk, SOCK_ZAPPED))
|
|
Takashi Iwai |
ce744d |
err = bt_sock_wait_state(sk, BT_CONNECTED,
|
|
Takashi Iwai |
ce744d |
sock_sndtimeo(sk, flags & O_NONBLOCK));
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
done:
|
|
Takashi Iwai |
ce744d |
release_sock(sk);
|
|
Takashi Iwai |
ce744d |
+ sock_put(sk);
|
|
Takashi Iwai |
ce744d |
return err;
|
|
Takashi Iwai |
ce744d |
}
|
|
Takashi Iwai |
ce744d |
|
|
Takashi Iwai |
ce744d |
--
|
|
Takashi Iwai |
ce744d |
2.35.3
|
|
Takashi Iwai |
ce744d |
|