lkml.org 
[lkml]   [2021]   [Nov]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 167/575] Bluetooth: sco: Fix lock_sock() blockage by memcpy_from_msg()
    Date
    From: Takashi Iwai <tiwai@suse.de>

    [ Upstream commit 99c23da0eed4fd20cae8243f2b51e10e66aa0951 ]

    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 <tiwai@suse.de>
    Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/bluetooth/sco.c | 24 ++++++++++++++++--------
    1 file changed, 16 insertions(+), 8 deletions(-)

    diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
    index 7c24a9acbc459..93df269a64707 100644
    --- a/net/bluetooth/sco.c
    +++ b/net/bluetooth/sco.c
    @@ -281,7 +281,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;
    @@ -293,15 +294,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;
    @@ -726,6 +723,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);
    @@ -737,14 +735,24 @@ 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.33.0


    \
     
     \ /
      Last update: 2021-11-15 20:40    [W:3.346 / U:1.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site