This is a note to let you know that I've just added the patch titled Bluetooth: Fix possible deadlock in rfcomm_sk_state_change to the 5.15-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: bluetooth-fix-possible-deadlock-in-rfcomm_sk_state_c.patch and it can be found in the queue-5.15 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 888092ae3cdacba3d684d40a1917087e1ee94dfc Author: Ying Hsu <yinghsu@xxxxxxxxxxxx> Date: Wed Jan 11 03:16:14 2023 +0000 Bluetooth: Fix possible deadlock in rfcomm_sk_state_change [ Upstream commit 1d80d57ffcb55488f0ec0b77928d4f82d16b6a90 ] syzbot reports a possible deadlock in rfcomm_sk_state_change [1]. While rfcomm_sock_connect acquires the sk lock and waits for the rfcomm lock, rfcomm_sock_release could have the rfcomm lock and hit a deadlock for acquiring the sk lock. Here's a simplified flow: rfcomm_sock_connect: lock_sock(sk) rfcomm_dlc_open: rfcomm_lock() rfcomm_sock_release: rfcomm_sock_shutdown: rfcomm_lock() __rfcomm_dlc_close: rfcomm_k_state_change: lock_sock(sk) This patch drops the sk lock before calling rfcomm_dlc_open to avoid the possible deadlock and holds sk's reference count to prevent use-after-free after rfcomm_dlc_open completes. Reported-by: syzbot+d7ce59...@xxxxxxxxxxxxxxxxxxxxxxxxx Fixes: 1804fdf6e494 ("Bluetooth: btintel: Combine setting up MSFT extension") Link: https://syzkaller.appspot.com/bug?extid=d7ce59b06b3eb14fd218 [1] Signed-off-by: Ying Hsu <yinghsu@xxxxxxxxxxxx> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 21e24da4847f..4397e14ff560 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -391,6 +391,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a addr->sa_family != AF_BLUETOOTH) return -EINVAL; + sock_hold(sk); lock_sock(sk); if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) { @@ -410,14 +411,18 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a d->sec_level = rfcomm_pi(sk)->sec_level; d->role_switch = rfcomm_pi(sk)->role_switch; + /* Drop sock lock to avoid potential deadlock with the RFCOMM lock */ + release_sock(sk); err = rfcomm_dlc_open(d, &rfcomm_pi(sk)->src, &sa->rc_bdaddr, sa->rc_channel); - if (!err) + lock_sock(sk); + if (!err && !sock_flag(sk, SOCK_ZAPPED)) err = bt_sock_wait_state(sk, BT_CONNECTED, sock_sndtimeo(sk, flags & O_NONBLOCK)); done: release_sock(sk); + sock_put(sk); return err; }