From: Luiz Augusto von Dentz luiz.von.dentz@intel.com
mainline inclusion from mainline-v6.10-rc7 commit f1a8f402f13f94263cf349216c257b2985100927 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAGEK1 CVE: CVE-2024-41062
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------------------
This fixes the following deadlock introduced by 39a92a55be13 ("bluetooth/l2cap: sync sock recv cb and release")
============================================ WARNING: possible recursive locking detected 6.10.0-rc3-g4029dba6b6f1 #6823 Not tainted -------------------------------------------- kworker/u5:0/35 is trying to acquire lock: ffff888002ec2510 (&chan->lock#2/1){+.+.}-{3:3}, at: l2cap_sock_recv_cb+0x44/0x1e0
but task is already holding lock: ffff888002ec2510 (&chan->lock#2/1){+.+.}-{3:3}, at: l2cap_get_chan_by_scid+0xaf/0xd0
other info that might help us debug this: Possible unsafe locking scenario:
CPU0 ---- lock(&chan->lock#2/1); lock(&chan->lock#2/1);
*** DEADLOCK ***
May be due to missing lock nesting notation
3 locks held by kworker/u5:0/35: #0: ffff888002b8a940 ((wq_completion)hci0#2){+.+.}-{0:0}, at: process_one_work+0x750/0x930 #1: ffff888002c67dd0 ((work_completion)(&hdev->rx_work)){+.+.}-{0:0}, at: process_one_work+0x44e/0x930 #2: ffff888002ec2510 (&chan->lock#2/1){+.+.}-{3:3}, at: l2cap_get_chan_by_scid+0xaf/0xd0
To fix the original problem this introduces l2cap_chan_lock at l2cap_conless_channel to ensure that l2cap_sock_recv_cb is called with chan->lock held.
Fixes: 89e856e124f9 ("bluetooth/l2cap: sync sock recv cb and release") Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com
Conflicts: include/net/bluetooth/hci_sync.h net/bluetooth/hci_core.c net/bluetooth/hci_sync.c net/bluetooth/l2cap_core.c net/bluetooth/l2cap_sock.c [The conflict occurs because the commit ce60b9231b66("Bluetooth: compute LE flow credits based on recvbuf space") is not merged. The replacement of the __hci_cmd_sync_status function is not the code that solves the problem in the patch. For details, see the initial maillist information. https://patchwork.kernel.org/project/bluetooth/patch/20240624134637.37 90278-1-luiz.dentz@gmail.com/] Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com --- net/bluetooth/l2cap_core.c | 3 +++ net/bluetooth/l2cap_sock.c | 12 +----------- 2 files changed, 4 insertions(+), 11 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c3b6a416119e..707076552f0b 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -7713,6 +7713,8 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
BT_DBG("chan %p, len %d", chan, skb->len);
+ l2cap_chan_lock(chan); + if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) goto drop;
@@ -7729,6 +7731,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, }
drop: + l2cap_chan_unlock(chan); l2cap_chan_put(chan); free_skb: kfree_skb(skb); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index c7217d3ecd8b..51927765473b 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1487,17 +1487,9 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) struct sock *sk; int err;
- /* To avoid race with sock_release, a chan lock needs to be added here - * to synchronize the sock. - */ - l2cap_chan_hold(chan); - l2cap_chan_lock(chan); sk = chan->data; - if (!sk) { - l2cap_chan_unlock(chan); - l2cap_chan_put(chan); + if (!sk) return -ENXIO; - }
lock_sock(sk);
@@ -1535,8 +1527,6 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
done: release_sock(sk); - l2cap_chan_unlock(chan); - l2cap_chan_put(chan);
return err; }