--- /dev/null
+From 97e4e80299844bb5f6ce5a7540742ffbffae3d97 Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Fri, 3 Sep 2021 15:27:30 -0700
+Subject: Bluetooth: Add bt_skb_sendmmsg helper
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+commit 97e4e80299844bb5f6ce5a7540742ffbffae3d97 upstream.
+
+This works similarly to bt_skb_sendmsg but can split the msg into
+multiple skb fragments which is useful for stream sockets.
+
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Cc: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/bluetooth/bluetooth.h | 38 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -450,6 +450,44 @@ static inline struct sk_buff *bt_skb_sen
+ return skb;
+ }
+
++/* Similar to bt_skb_sendmsg but can split the msg into multiple fragments
++ * accourding to the MTU.
++ */
++static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
++ struct msghdr *msg,
++ size_t len, size_t mtu,
++ size_t headroom, size_t tailroom)
++{
++ struct sk_buff *skb, **frag;
++
++ skb = bt_skb_sendmsg(sk, msg, len, mtu, headroom, tailroom);
++ if (IS_ERR_OR_NULL(skb))
++ return skb;
++
++ len -= skb->len;
++ if (!len)
++ return skb;
++
++ /* Add remaining data over MTU as continuation fragments */
++ frag = &skb_shinfo(skb)->frag_list;
++ while (len) {
++ struct sk_buff *tmp;
++
++ tmp = bt_skb_sendmsg(sk, msg, len, mtu, headroom, tailroom);
++ if (IS_ERR_OR_NULL(tmp)) {
++ kfree_skb(skb);
++ return tmp;
++ }
++
++ len -= tmp->len;
++
++ *frag = tmp;
++ frag = &(*frag)->next;
++ }
++
++ return skb;
++}
++
+ int bt_to_errno(u16 code);
+
+ void hci_sock_set_flag(struct sock *sk, int nr);
--- /dev/null
+From 38f64f650dc0e44c146ff88d15a7339efa325918 Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Fri, 3 Sep 2021 15:27:29 -0700
+Subject: Bluetooth: Add bt_skb_sendmsg helper
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+commit 38f64f650dc0e44c146ff88d15a7339efa325918 upstream.
+
+bt_skb_sendmsg helps takes care of allocation the skb and copying the
+the contents of msg over to the skb while checking for possible errors
+so it should be safe to call it without holding lock_sock.
+
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Cc: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/bluetooth/bluetooth.h | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -422,6 +422,34 @@ out:
+ return NULL;
+ }
+
++/* Shall not be called with lock_sock held */
++static inline struct sk_buff *bt_skb_sendmsg(struct sock *sk,
++ struct msghdr *msg,
++ size_t len, size_t mtu,
++ size_t headroom, size_t tailroom)
++{
++ struct sk_buff *skb;
++ size_t size = min_t(size_t, len, mtu);
++ int err;
++
++ skb = bt_skb_send_alloc(sk, size + headroom + tailroom,
++ msg->msg_flags & MSG_DONTWAIT, &err);
++ if (!skb)
++ return ERR_PTR(err);
++
++ skb_reserve(skb, headroom);
++ skb_tailroom_reserve(skb, mtu, tailroom);
++
++ if (!copy_from_iter_full(skb_put(skb, size), size, &msg->msg_iter)) {
++ kfree_skb(skb);
++ return ERR_PTR(-EFAULT);
++ }
++
++ skb->priority = sk->sk_priority;
++
++ return skb;
++}
++
+ int bt_to_errno(u16 code);
+
+ void hci_sock_set_flag(struct sock *sk, int nr);
--- /dev/null
+From 29fb608396d6a62c1b85acc421ad7a4399085b9f Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Mon, 14 Feb 2022 17:59:38 -0800
+Subject: Bluetooth: Fix bt_skb_sendmmsg not allocating partial chunks
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+commit 29fb608396d6a62c1b85acc421ad7a4399085b9f upstream.
+
+Since bt_skb_sendmmsg can be used with the likes of SOCK_STREAM it
+shall return the partial chunks it could allocate instead of freeing
+everything as otherwise it can cause problems like bellow.
+
+Fixes: 81be03e026dc ("Bluetooth: RFCOMM: Replace use of memcpy_from_msg with bt_skb_sendmmsg")
+Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Link: https://lore.kernel.org/r/d7206e12-1b99-c3be-84f4-df22af427ef5@molgen.mpg.de
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=215594
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Tested-by: Paul Menzel <pmenzel@molgen.mpg.de> (Nokia N9 (MeeGo/Harmattan)
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Cc: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/bluetooth/bluetooth.h | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -475,8 +475,7 @@ static inline struct sk_buff *bt_skb_sen
+
+ tmp = bt_skb_sendmsg(sk, msg, len, mtu, headroom, tailroom);
+ if (IS_ERR(tmp)) {
+- kfree_skb(skb);
+- return tmp;
++ return skb;
+ }
+
+ len -= tmp->len;
--- /dev/null
+From 266191aa8d14b84958aaeb5e96ee4e97839e3d87 Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Thu, 16 Sep 2021 13:10:48 -0700
+Subject: Bluetooth: Fix passing NULL to PTR_ERR
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+commit 266191aa8d14b84958aaeb5e96ee4e97839e3d87 upstream.
+
+Passing NULL to PTR_ERR will result in 0 (success), also since the likes of
+bt_skb_sendmsg does never return NULL it is safe to replace the instances of
+IS_ERR_OR_NULL with IS_ERR when checking its return.
+
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Tested-by: Tedd Ho-Jeong An <tedd.an@intel.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Cc: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/bluetooth/bluetooth.h | 2 +-
+ net/bluetooth/rfcomm/sock.c | 2 +-
+ net/bluetooth/sco.c | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -474,7 +474,7 @@ static inline struct sk_buff *bt_skb_sen
+ struct sk_buff *tmp;
+
+ tmp = bt_skb_sendmsg(sk, msg, len, mtu, headroom, tailroom);
+- if (IS_ERR_OR_NULL(tmp)) {
++ if (IS_ERR(tmp)) {
+ kfree_skb(skb);
+ return tmp;
+ }
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -583,7 +583,7 @@ static int rfcomm_sock_sendmsg(struct so
+
+ skb = bt_skb_sendmmsg(sk, msg, len, d->mtu, RFCOMM_SKB_HEAD_RESERVE,
+ RFCOMM_SKB_TAIL_RESERVE);
+- if (IS_ERR_OR_NULL(skb))
++ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ sent = rfcomm_dlc_send(d, skb);
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -732,7 +732,7 @@ static int sco_sock_sendmsg(struct socke
+ return -EOPNOTSUPP;
+
+ skb = bt_skb_sendmsg(sk, msg, len, len, 0, 0);
+- if (IS_ERR_OR_NULL(skb))
++ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ lock_sock(sk);
--- /dev/null
+From 81be03e026dc0c16dc1c64e088b2a53b73caa895 Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Fri, 3 Sep 2021 15:27:32 -0700
+Subject: Bluetooth: RFCOMM: Replace use of memcpy_from_msg with bt_skb_sendmmsg
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+commit 81be03e026dc0c16dc1c64e088b2a53b73caa895 upstream.
+
+This makes use of bt_skb_sendmmsg instead using memcpy_from_msg which
+is not considered safe to be used when lock_sock is held.
+
+Also make rfcomm_dlc_send handle skb with fragments and queue them all
+atomically.
+
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Cc: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/rfcomm/core.c | 50 +++++++++++++++++++++++++++++++++++++-------
+ net/bluetooth/rfcomm/sock.c | 50 ++++++++++----------------------------------
+ 2 files changed, 55 insertions(+), 45 deletions(-)
+
+--- a/net/bluetooth/rfcomm/core.c
++++ b/net/bluetooth/rfcomm/core.c
+@@ -549,22 +549,58 @@ struct rfcomm_dlc *rfcomm_dlc_exists(bda
+ return dlc;
+ }
+
++static int rfcomm_dlc_send_frag(struct rfcomm_dlc *d, struct sk_buff *frag)
++{
++ int len = frag->len;
++
++ BT_DBG("dlc %p mtu %d len %d", d, d->mtu, len);
++
++ if (len > d->mtu)
++ return -EINVAL;
++
++ rfcomm_make_uih(frag, d->addr);
++ __skb_queue_tail(&d->tx_queue, frag);
++
++ return len;
++}
++
+ int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb)
+ {
+- int len = skb->len;
++ unsigned long flags;
++ struct sk_buff *frag, *next;
++ int len;
+
+ if (d->state != BT_CONNECTED)
+ return -ENOTCONN;
+
+- BT_DBG("dlc %p mtu %d len %d", d, d->mtu, len);
++ frag = skb_shinfo(skb)->frag_list;
++ skb_shinfo(skb)->frag_list = NULL;
+
+- if (len > d->mtu)
+- return -EINVAL;
++ /* Queue all fragments atomically. */
++ spin_lock_irqsave(&d->tx_queue.lock, flags);
++
++ len = rfcomm_dlc_send_frag(d, skb);
++ if (len < 0 || !frag)
++ goto unlock;
++
++ for (; frag; frag = next) {
++ int ret;
++
++ next = frag->next;
++
++ ret = rfcomm_dlc_send_frag(d, frag);
++ if (ret < 0) {
++ kfree_skb(frag);
++ goto unlock;
++ }
++
++ len += ret;
++ }
+
+- rfcomm_make_uih(skb, d->addr);
+- skb_queue_tail(&d->tx_queue, skb);
++unlock:
++ spin_unlock_irqrestore(&d->tx_queue.lock, flags);
+
+- if (!test_bit(RFCOMM_TX_THROTTLED, &d->flags))
++ if (len > 0 && !test_bit(RFCOMM_TX_THROTTLED, &d->flags))
+ rfcomm_schedule();
+ return len;
+ }
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -575,47 +575,21 @@ static int rfcomm_sock_sendmsg(struct so
+ lock_sock(sk);
+
+ sent = bt_sock_wait_ready(sk, msg->msg_flags);
+- if (sent)
+- goto done;
+-
+- while (len) {
+- size_t size = min_t(size_t, len, d->mtu);
+- int err;
+-
+- skb = sock_alloc_send_skb(sk, size + RFCOMM_SKB_RESERVE,
+- msg->msg_flags & MSG_DONTWAIT, &err);
+- if (!skb) {
+- if (sent == 0)
+- sent = err;
+- break;
+- }
+- skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);
+-
+- err = memcpy_from_msg(skb_put(skb, size), msg, size);
+- if (err) {
+- kfree_skb(skb);
+- if (sent == 0)
+- sent = err;
+- break;
+- }
+-
+- skb->priority = sk->sk_priority;
+-
+- err = rfcomm_dlc_send(d, skb);
+- if (err < 0) {
+- kfree_skb(skb);
+- if (sent == 0)
+- sent = err;
+- break;
+- }
+-
+- sent += size;
+- len -= size;
+- }
+
+-done:
+ release_sock(sk);
+
++ if (sent)
++ return sent;
++
++ skb = bt_skb_sendmmsg(sk, msg, len, d->mtu, RFCOMM_SKB_HEAD_RESERVE,
++ RFCOMM_SKB_TAIL_RESERVE);
++ if (IS_ERR_OR_NULL(skb))
++ return PTR_ERR(skb);
++
++ sent = rfcomm_dlc_send(d, skb);
++ if (sent < 0)
++ kfree_skb(skb);
++
+ return sent;
+ }
+
--- /dev/null
+From 037ce005af6b8a3e40ee07c6e9266c8997e6a4d6 Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Thu, 16 Sep 2021 13:10:49 -0700
+Subject: Bluetooth: SCO: Fix sco_send_frame returning skb->len
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+commit 037ce005af6b8a3e40ee07c6e9266c8997e6a4d6 upstream.
+
+The skb in modified by hci_send_sco which pushes SCO headers thus
+changing skb->len causing sco_sock_sendmsg to fail.
+
+Fixes: 0771cbb3b97d ("Bluetooth: SCO: Replace use of memcpy_from_msg with bt_skb_sendmsg")
+Tested-by: Tedd Ho-Jeong An <tedd.an@intel.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Cc: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/sco.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -283,16 +283,17 @@ static int sco_connect(struct hci_dev *h
+ static int sco_send_frame(struct sock *sk, struct sk_buff *skb)
+ {
+ struct sco_conn *conn = sco_pi(sk)->conn;
++ int len = skb->len;
+
+ /* Check outgoing MTU */
+- if (skb->len > conn->mtu)
++ if (len > conn->mtu)
+ return -EINVAL;
+
+- BT_DBG("sk %p len %d", sk, skb->len);
++ BT_DBG("sk %p len %d", sk, len);
+
+ hci_send_sco(conn->hcon, skb);
+
+- return skb->len;
++ return len;
+ }
+
+ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
+@@ -743,7 +744,8 @@ static int sco_sock_sendmsg(struct socke
+ err = -ENOTCONN;
+
+ release_sock(sk);
+- if (err)
++
++ if (err < 0)
+ kfree_skb(skb);
+ return err;
+ }
--- /dev/null
+From 0771cbb3b97d3c1d68eecd7f00055f599954c34e Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Fri, 3 Sep 2021 15:27:31 -0700
+Subject: Bluetooth: SCO: Replace use of memcpy_from_msg with bt_skb_sendmsg
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+commit 0771cbb3b97d3c1d68eecd7f00055f599954c34e upstream.
+
+This makes use of bt_skb_sendmsg instead of allocating a different
+buffer to be used with memcpy_from_msg which cause one extra copy.
+
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Cc: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/sco.c | 34 +++++++++++-----------------------
+ 1 file changed, 11 insertions(+), 23 deletions(-)
+
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -280,27 +280,19 @@ static int sco_connect(struct hci_dev *h
+ return err;
+ }
+
+-static int sco_send_frame(struct sock *sk, void *buf, int len,
+- unsigned int msg_flags)
++static int sco_send_frame(struct sock *sk, struct sk_buff *skb)
+ {
+ struct sco_conn *conn = sco_pi(sk)->conn;
+- struct sk_buff *skb;
+- int err;
+
+ /* Check outgoing MTU */
+- if (len > conn->mtu)
++ if (skb->len > conn->mtu)
+ return -EINVAL;
+
+- BT_DBG("sk %p len %d", sk, len);
++ BT_DBG("sk %p len %d", sk, skb->len);
+
+- skb = bt_skb_send_alloc(sk, len, msg_flags & MSG_DONTWAIT, &err);
+- if (!skb)
+- return err;
+-
+- memcpy(skb_put(skb, len), buf, len);
+ hci_send_sco(conn->hcon, skb);
+
+- return len;
++ return skb->len;
+ }
+
+ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
+@@ -727,7 +719,7 @@ static int sco_sock_sendmsg(struct socke
+ size_t len)
+ {
+ struct sock *sk = sock->sk;
+- void *buf;
++ struct sk_buff *skb;
+ int err;
+
+ BT_DBG("sock %p, sk %p", sock, sk);
+@@ -739,24 +731,20 @@ static int sco_sock_sendmsg(struct socke
+ 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;
+- }
++ skb = bt_skb_sendmsg(sk, msg, len, len, 0, 0);
++ if (IS_ERR_OR_NULL(skb))
++ return PTR_ERR(skb);
+
+ lock_sock(sk);
+
+ if (sk->sk_state == BT_CONNECTED)
+- err = sco_send_frame(sk, buf, len, msg->msg_flags);
++ err = sco_send_frame(sk, skb);
+ else
+ err = -ENOTCONN;
+
+ release_sock(sk);
+- kfree(buf);
++ if (err)
++ kfree_skb(skb);
+ return err;
+ }
+
um-virtio_uml-allow-probing-from-devicetree.patch
um-virtio_uml-fix-broken-device-handling-in-time-tra.patch
x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch-12415
+bluetooth-add-bt_skb_sendmsg-helper.patch
+bluetooth-add-bt_skb_sendmmsg-helper.patch
+bluetooth-sco-replace-use-of-memcpy_from_msg-with-bt_skb_sendmsg.patch
+bluetooth-rfcomm-replace-use-of-memcpy_from_msg-with-bt_skb_sendmmsg.patch
+bluetooth-fix-passing-null-to-ptr_err.patch
+bluetooth-sco-fix-sco_send_frame-returning-skb-len.patch
+bluetooth-fix-bt_skb_sendmmsg-not-allocating-partial-chunks.patch
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
- arch/x86/include/asm/uaccess.h | 97 ++++++++++++++++++++++++++++++++++
+ arch/x86/include/asm/uaccess.h | 97 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
-diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
-index 775f1162da74..9af1a27fa568 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -608,6 +608,103 @@ do { \
/* FIXME: this hack is definitely wrong -AK */
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct __user *)(x))
---
-2.35.1
-