| From stable+bounces-226955-greg=kroah.com@vger.kernel.org Wed Mar 18 05:41:13 2026 |
| From: Johnny Hao <johnny_haocn@sina.com> |
| Date: Wed, 18 Mar 2026 12:40:10 +0800 |
| Subject: Bluetooth: af_bluetooth: Fix deadlock |
| To: gregkh@linuxfoundation.org, stable@vger.kernel.org |
| Cc: linux-kernel@vger.kernel.org, Luiz Augusto von Dentz <luiz.von.dentz@intel.com>, Johnny Hao <johnny_haocn@sina.com> |
| Message-ID: <20260318044010.3507623-1-johnny_haocn@sina.com> |
| |
| From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> |
| |
| [ Upstream commit f7b94bdc1ec107c92262716b073b3e816d4784fb ] |
| |
| Attemting to do sock_lock on .recvmsg may cause a deadlock as shown |
| bellow, so instead of using sock_sock this uses sk_receive_queue.lock |
| on bt_sock_ioctl to avoid the UAF: |
| |
| INFO: task kworker/u9:1:121 blocked for more than 30 seconds. |
| Not tainted 6.7.6-lemon #183 |
| Workqueue: hci0 hci_rx_work |
| Call Trace: |
| <TASK> |
| __schedule+0x37d/0xa00 |
| schedule+0x32/0xe0 |
| __lock_sock+0x68/0xa0 |
| ? __pfx_autoremove_wake_function+0x10/0x10 |
| lock_sock_nested+0x43/0x50 |
| l2cap_sock_recv_cb+0x21/0xa0 |
| l2cap_recv_frame+0x55b/0x30a0 |
| ? psi_task_switch+0xeb/0x270 |
| ? finish_task_switch.isra.0+0x93/0x2a0 |
| hci_rx_work+0x33a/0x3f0 |
| process_one_work+0x13a/0x2f0 |
| worker_thread+0x2f0/0x410 |
| ? __pfx_worker_thread+0x10/0x10 |
| kthread+0xe0/0x110 |
| ? __pfx_kthread+0x10/0x10 |
| ret_from_fork+0x2c/0x50 |
| ? __pfx_kthread+0x10/0x10 |
| ret_from_fork_asm+0x1b/0x30 |
| </TASK> |
| |
| Fixes: 2e07e8348ea4 ("Bluetooth: af_bluetooth: Fix Use-After-Free in bt_sock_recvmsg") |
| Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> |
| [ The context change is due to the commit f4b41f062c42 |
| ("net: remove noblock parameter from skb_recv_datagram()") |
| in v5.19 which is irrelevant to the logic of this patch. ] |
| Signed-off-by: Johnny Hao <johnny_haocn@sina.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/bluetooth/af_bluetooth.c | 10 +++------- |
| 1 file changed, 3 insertions(+), 7 deletions(-) |
| |
| --- a/net/bluetooth/af_bluetooth.c |
| +++ b/net/bluetooth/af_bluetooth.c |
| @@ -285,14 +285,11 @@ int bt_sock_recvmsg(struct socket *sock, |
| if (flags & MSG_OOB) |
| return -EOPNOTSUPP; |
| |
| - lock_sock(sk); |
| - |
| skb = skb_recv_datagram(sk, flags, noblock, &err); |
| if (!skb) { |
| if (sk->sk_shutdown & RCV_SHUTDOWN) |
| err = 0; |
| |
| - release_sock(sk); |
| return err; |
| } |
| |
| @@ -318,8 +315,6 @@ int bt_sock_recvmsg(struct socket *sock, |
| |
| skb_free_datagram(sk, skb); |
| |
| - release_sock(sk); |
| - |
| if (flags & MSG_TRUNC) |
| copied = skblen; |
| |
| @@ -542,10 +537,11 @@ int bt_sock_ioctl(struct socket *sock, u |
| if (sk->sk_state == BT_LISTEN) |
| return -EINVAL; |
| |
| - lock_sock(sk); |
| + spin_lock(&sk->sk_receive_queue.lock); |
| skb = skb_peek(&sk->sk_receive_queue); |
| amount = skb ? skb->len : 0; |
| - release_sock(sk); |
| + spin_unlock(&sk->sk_receive_queue.lock); |
| + |
| err = put_user(amount, (int __user *)arg); |
| break; |
| |