2021-08-28 16:19:20

by Takashi Iwai

[permalink] [raw]
Subject: [PATCH] Bluetooth: sco: Fix lock_sock() blockage by memcpy_from_msg()

The sco_send_frame() also takes lock_sock() during memcpy_from_msg()
call that may be endlessly blocked by a task with userfaultd
technique, and this will result in a hung task watchdog trigger.

Just like the similar fix for hci_sock_sendmsg() in commit
92c685dc5de0 ("Bluetooth: reorganize functions..."), this patch moves
the memcpy_from_msg() out of lock_sock() for addressing the hang.

This should be the last piece for fixing CVE-2021-3640 after a few
already queued fixes.

Signed-off-by: Takashi Iwai <[email protected]>
---
net/bluetooth/sco.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 98a881586512..687e05718aad 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -280,7 +280,8 @@ static int sco_connect(struct hci_dev *hdev, struct sock *sk)
return err;
}

-static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
+static int sco_send_frame(struct sock *sk, void *buf, int len,
+ unsigned int msg_flags)
{
struct sco_conn *conn = sco_pi(sk)->conn;
struct sk_buff *skb;
@@ -292,15 +293,11 @@ static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)

BT_DBG("sk %p len %d", sk, len);

- skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
+ skb = bt_skb_send_alloc(sk, len, msg_flags & MSG_DONTWAIT, &err);
if (!skb)
return err;

- if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
- kfree_skb(skb);
- return -EFAULT;
- }
-
+ memcpy(skb_put(skb, len), buf, len);
hci_send_sco(conn->hcon, skb);

return len;
@@ -725,6 +722,7 @@ static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg,
size_t len)
{
struct sock *sk = sock->sk;
+ void *buf;
int err;

BT_DBG("sock %p, sk %p", sock, sk);
@@ -736,14 +734,23 @@ static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg,
if (msg->msg_flags & MSG_OOB)
return -EOPNOTSUPP;

+ buf = kmalloc(len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ if (memcpy_from_msg(buf, msg, len)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+
lock_sock(sk);

if (sk->sk_state == BT_CONNECTED)
- err = sco_send_frame(sk, msg, len);
+ err = sco_send_frame(sk, buf, len, msg->msg_flags);
else
err = -ENOTCONN;

release_sock(sk);
+ kfree(buf);
return err;
}

--
2.26.2


2021-08-30 14:51:49

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH] Bluetooth: sco: Fix lock_sock() blockage by memcpy_from_msg()

Hi Takashi,

> The sco_send_frame() also takes lock_sock() during memcpy_from_msg()
> call that may be endlessly blocked by a task with userfaultd
> technique, and this will result in a hung task watchdog trigger.
>
> Just like the similar fix for hci_sock_sendmsg() in commit
> 92c685dc5de0 ("Bluetooth: reorganize functions..."), this patch moves
> the memcpy_from_msg() out of lock_sock() for addressing the hang.
>
> This should be the last piece for fixing CVE-2021-3640 after a few
> already queued fixes.
>
> Signed-off-by: Takashi Iwai <[email protected]>
> ---
> net/bluetooth/sco.c | 23 +++++++++++++++--------
> 1 file changed, 15 insertions(+), 8 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel