]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Feb 2025 12:58:52 +0000 (13:58 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Feb 2025 12:58:52 +0000 (13:58 +0100)
added patches:
pinctrl-stm32-fix-array-read-out-of-bound.patch

queue-6.1/bpf-vsock-invoke-proto-close-on-close.patch [deleted file]
queue-6.1/pinctrl-stm32-fix-array-read-out-of-bound.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/vsock-allow-retrying-on-connect-failure.patch [deleted file]
queue-6.1/vsock-keep-the-binding-until-socket-destruction.patch [deleted file]
queue-6.1/vsock-support-sockmap.patch [deleted file]

diff --git a/queue-6.1/bpf-vsock-invoke-proto-close-on-close.patch b/queue-6.1/bpf-vsock-invoke-proto-close-on-close.patch
deleted file mode 100644 (file)
index cf4ee1e..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-From 731abe55c67c849d2ca1122baa608711da2bda50 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 18 Nov 2024 22:03:43 +0100
-Subject: bpf, vsock: Invoke proto::close on close()
-
-From: Michal Luczaj <mhal@rbox.co>
-
-[ Upstream commit 135ffc7becc82cfb84936ae133da7969220b43b2 ]
-
-vsock defines a BPF callback to be invoked when close() is called. However,
-this callback is never actually executed. As a result, a closed vsock
-socket is not automatically removed from the sockmap/sockhash.
-
-Introduce a dummy vsock_close() and make vsock_release() call proto::close.
-
-Note: changes in __vsock_release() look messy, but it's only due to indent
-level reduction and variables xmas tree reorder.
-
-Fixes: 634f1a7110b4 ("vsock: support sockmap")
-Signed-off-by: Michal Luczaj <mhal@rbox.co>
-Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
-Reviewed-by: Luigi Leonardi <leonardi@redhat.com>
-Link: https://lore.kernel.org/r/20241118-vsock-bpf-poll-close-v1-3-f1b9669cacdc@rbox.co
-Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-Acked-by: John Fastabend <john.fastabend@gmail.com>
-Stable-dep-of: fcdd2242c023 ("vsock: Keep the binding until socket destruction")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/vmw_vsock/af_vsock.c | 67 ++++++++++++++++++++++++----------------
- 1 file changed, 40 insertions(+), 27 deletions(-)
-
-diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
-index e0107c873f261..7ad84c6c19c3e 100644
---- a/net/vmw_vsock/af_vsock.c
-+++ b/net/vmw_vsock/af_vsock.c
-@@ -116,12 +116,14 @@
- static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr);
- static void vsock_sk_destruct(struct sock *sk);
- static int vsock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
-+static void vsock_close(struct sock *sk, long timeout);
- /* Protocol family. */
- struct proto vsock_proto = {
-       .name = "AF_VSOCK",
-       .owner = THIS_MODULE,
-       .obj_size = sizeof(struct vsock_sock),
-+      .close = vsock_close,
- #ifdef CONFIG_BPF_SYSCALL
-       .psock_update_sk_prot = vsock_bpf_update_proto,
- #endif
-@@ -806,39 +808,37 @@ static bool sock_type_connectible(u16 type)
- static void __vsock_release(struct sock *sk, int level)
- {
--      if (sk) {
--              struct sock *pending;
--              struct vsock_sock *vsk;
--
--              vsk = vsock_sk(sk);
--              pending = NULL; /* Compiler warning. */
-+      struct vsock_sock *vsk;
-+      struct sock *pending;
--              /* When "level" is SINGLE_DEPTH_NESTING, use the nested
--               * version to avoid the warning "possible recursive locking
--               * detected". When "level" is 0, lock_sock_nested(sk, level)
--               * is the same as lock_sock(sk).
--               */
--              lock_sock_nested(sk, level);
-+      vsk = vsock_sk(sk);
-+      pending = NULL; /* Compiler warning. */
--              if (vsk->transport)
--                      vsk->transport->release(vsk);
--              else if (sock_type_connectible(sk->sk_type))
--                      vsock_remove_sock(vsk);
-+      /* When "level" is SINGLE_DEPTH_NESTING, use the nested
-+       * version to avoid the warning "possible recursive locking
-+       * detected". When "level" is 0, lock_sock_nested(sk, level)
-+       * is the same as lock_sock(sk).
-+       */
-+      lock_sock_nested(sk, level);
--              sock_orphan(sk);
--              sk->sk_shutdown = SHUTDOWN_MASK;
-+      if (vsk->transport)
-+              vsk->transport->release(vsk);
-+      else if (sock_type_connectible(sk->sk_type))
-+              vsock_remove_sock(vsk);
--              skb_queue_purge(&sk->sk_receive_queue);
-+      sock_orphan(sk);
-+      sk->sk_shutdown = SHUTDOWN_MASK;
--              /* Clean up any sockets that never were accepted. */
--              while ((pending = vsock_dequeue_accept(sk)) != NULL) {
--                      __vsock_release(pending, SINGLE_DEPTH_NESTING);
--                      sock_put(pending);
--              }
-+      skb_queue_purge(&sk->sk_receive_queue);
--              release_sock(sk);
--              sock_put(sk);
-+      /* Clean up any sockets that never were accepted. */
-+      while ((pending = vsock_dequeue_accept(sk)) != NULL) {
-+              __vsock_release(pending, SINGLE_DEPTH_NESTING);
-+              sock_put(pending);
-       }
-+
-+      release_sock(sk);
-+      sock_put(sk);
- }
- static void vsock_sk_destruct(struct sock *sk)
-@@ -916,9 +916,22 @@ void vsock_data_ready(struct sock *sk)
- }
- EXPORT_SYMBOL_GPL(vsock_data_ready);
-+/* Dummy callback required by sockmap.
-+ * See unconditional call of saved_close() in sock_map_close().
-+ */
-+static void vsock_close(struct sock *sk, long timeout)
-+{
-+}
-+
- static int vsock_release(struct socket *sock)
- {
--      __vsock_release(sock->sk, 0);
-+      struct sock *sk = sock->sk;
-+
-+      if (!sk)
-+              return 0;
-+
-+      sk->sk_prot->close(sk, 0);
-+      __vsock_release(sk, 0);
-       sock->sk = NULL;
-       sock->state = SS_FREE;
--- 
-2.39.5
-
diff --git a/queue-6.1/pinctrl-stm32-fix-array-read-out-of-bound.patch b/queue-6.1/pinctrl-stm32-fix-array-read-out-of-bound.patch
new file mode 100644 (file)
index 0000000..9ae2210
--- /dev/null
@@ -0,0 +1,41 @@
+From edd48fd9d45370d6c8ba0dd834fcc51ff688cc87 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <antonio.borneo@foss.st.com>
+Date: Tue, 7 Nov 2023 12:05:20 +0100
+Subject: pinctrl: stm32: fix array read out of bound
+
+From: Antonio Borneo <antonio.borneo@foss.st.com>
+
+commit edd48fd9d45370d6c8ba0dd834fcc51ff688cc87 upstream.
+
+The existing code does not verify if the "tentative" index exceeds
+the size of the array, causing out of bound read.
+Issue identified with kasan.
+
+Check the index before using it.
+
+Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
+Fixes: 32c170ff15b0 ("pinctrl: stm32: set default gpio line names using pin names")
+Link: https://lore.kernel.org/r/20231107110520.4449-1-antonio.borneo@foss.st.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pinctrl/stm32/pinctrl-stm32.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
++++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
+@@ -1282,9 +1282,11 @@ static struct stm32_desc_pin *stm32_pctr
+       int i;
+       /* With few exceptions (e.g. bank 'Z'), pin number matches with pin index in array */
+-      pin_desc = pctl->pins + stm32_pin_nb;
+-      if (pin_desc->pin.number == stm32_pin_nb)
+-              return pin_desc;
++      if (stm32_pin_nb < pctl->npins) {
++              pin_desc = pctl->pins + stm32_pin_nb;
++              if (pin_desc->pin.number == stm32_pin_nb)
++                      return pin_desc;
++      }
+       /* Otherwise, loop all array to find the pin with the right number */
+       for (i = 0; i < pctl->npins; i++) {
index 737c9837dd3ac1726eb76c063888cdd7b7d51aef..d9fa968ac211cf080d0eb9c853f4236c0d986265 100644 (file)
@@ -230,10 +230,6 @@ perf-trace-fix-runtime-error-of-index-out-of-bounds.patch
 pm-sleep-restore-asynchronous-device-resume-optimiza.patch
 pm-sleep-use-bool-for-all-1-bit-fields-in-struct-dev.patch
 pm-sleep-core-synchronize-runtime-pm-status-of-paren.patch
-vsock-support-sockmap.patch
-bpf-vsock-invoke-proto-close-on-close.patch
-vsock-keep-the-binding-until-socket-destruction.patch
-vsock-allow-retrying-on-connect-failure.patch
 bgmac-reduce-max-frame-size-to-support-just-mtu-1500.patch
 net-sh_eth-fix-missing-rtnl-lock-in-suspend-resume-p.patch
 net-hsr-fix-fill_frame_info-regression-vs-vlan-packe.patch
@@ -275,3 +271,4 @@ media-imx-jpeg-fix-potential-error-pointer-dereference-in-detach_pm.patch
 btrfs-output-the-reason-for-open_ctree-failure.patch
 ptp-properly-handle-compat-ioctls.patch
 s390-add-std-gnu11-to-decompressor-and-purgatory-cflags.patch
+pinctrl-stm32-fix-array-read-out-of-bound.patch
diff --git a/queue-6.1/vsock-allow-retrying-on-connect-failure.patch b/queue-6.1/vsock-allow-retrying-on-connect-failure.patch
deleted file mode 100644 (file)
index 30ed7f6..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From d3a46a60470293c3ad53c23cb2ac32a8ae18e156 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 28 Jan 2025 14:15:28 +0100
-Subject: vsock: Allow retrying on connect() failure
-
-From: Michal Luczaj <mhal@rbox.co>
-
-[ Upstream commit aa388c72113b7458127b709bdd7d3628af26e9b4 ]
-
-sk_err is set when a (connectible) connect() fails. Effectively, this makes
-an otherwise still healthy SS_UNCONNECTED socket impossible to use for any
-subsequent connection attempts.
-
-Clear sk_err upon trying to establish a connection.
-
-Fixes: d021c344051a ("VSOCK: Introduce VM Sockets")
-Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
-Reviewed-by: Luigi Leonardi <leonardi@redhat.com>
-Signed-off-by: Michal Luczaj <mhal@rbox.co>
-Link: https://patch.msgid.link/20250128-vsock-transport-vs-autobind-v3-2-1cf57065b770@rbox.co
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/vmw_vsock/af_vsock.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
-index a224769566589..0194bcf7e242d 100644
---- a/net/vmw_vsock/af_vsock.c
-+++ b/net/vmw_vsock/af_vsock.c
-@@ -1453,6 +1453,11 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr,
-               if (err < 0)
-                       goto out;
-+              /* sk_err might have been set as a result of an earlier
-+               * (failed) connect attempt.
-+               */
-+              sk->sk_err = 0;
-+
-               /* Mark sock as connecting and set the error code to in
-                * progress in case this is a non-blocking connect.
-                */
--- 
-2.39.5
-
diff --git a/queue-6.1/vsock-keep-the-binding-until-socket-destruction.patch b/queue-6.1/vsock-keep-the-binding-until-socket-destruction.patch
deleted file mode 100644 (file)
index 4453192..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-From dd8cb65af0ef10d3d6f6aca093a9d405bc6378f2 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 28 Jan 2025 14:15:27 +0100
-Subject: vsock: Keep the binding until socket destruction
-
-From: Michal Luczaj <mhal@rbox.co>
-
-[ Upstream commit fcdd2242c0231032fc84e1404315c245ae56322a ]
-
-Preserve sockets bindings; this includes both resulting from an explicit
-bind() and those implicitly bound through autobind during connect().
-
-Prevents socket unbinding during a transport reassignment, which fixes a
-use-after-free:
-
-    1. vsock_create() (refcnt=1) calls vsock_insert_unbound() (refcnt=2)
-    2. transport->release() calls vsock_remove_bound() without checking if
-       sk was bound and moved to bound list (refcnt=1)
-    3. vsock_bind() assumes sk is in unbound list and before
-       __vsock_insert_bound(vsock_bound_sockets()) calls
-       __vsock_remove_bound() which does:
-           list_del_init(&vsk->bound_table); // nop
-           sock_put(&vsk->sk);               // refcnt=0
-
-BUG: KASAN: slab-use-after-free in __vsock_bind+0x62e/0x730
-Read of size 4 at addr ffff88816b46a74c by task a.out/2057
- dump_stack_lvl+0x68/0x90
- print_report+0x174/0x4f6
- kasan_report+0xb9/0x190
- __vsock_bind+0x62e/0x730
- vsock_bind+0x97/0xe0
- __sys_bind+0x154/0x1f0
- __x64_sys_bind+0x6e/0xb0
- do_syscall_64+0x93/0x1b0
- entry_SYSCALL_64_after_hwframe+0x76/0x7e
-
-Allocated by task 2057:
- kasan_save_stack+0x1e/0x40
- kasan_save_track+0x10/0x30
- __kasan_slab_alloc+0x85/0x90
- kmem_cache_alloc_noprof+0x131/0x450
- sk_prot_alloc+0x5b/0x220
- sk_alloc+0x2c/0x870
- __vsock_create.constprop.0+0x2e/0xb60
- vsock_create+0xe4/0x420
- __sock_create+0x241/0x650
- __sys_socket+0xf2/0x1a0
- __x64_sys_socket+0x6e/0xb0
- do_syscall_64+0x93/0x1b0
- entry_SYSCALL_64_after_hwframe+0x76/0x7e
-
-Freed by task 2057:
- kasan_save_stack+0x1e/0x40
- kasan_save_track+0x10/0x30
- kasan_save_free_info+0x37/0x60
- __kasan_slab_free+0x4b/0x70
- kmem_cache_free+0x1a1/0x590
- __sk_destruct+0x388/0x5a0
- __vsock_bind+0x5e1/0x730
- vsock_bind+0x97/0xe0
- __sys_bind+0x154/0x1f0
- __x64_sys_bind+0x6e/0xb0
- do_syscall_64+0x93/0x1b0
- entry_SYSCALL_64_after_hwframe+0x76/0x7e
-
-refcount_t: addition on 0; use-after-free.
-WARNING: CPU: 7 PID: 2057 at lib/refcount.c:25 refcount_warn_saturate+0xce/0x150
-RIP: 0010:refcount_warn_saturate+0xce/0x150
- __vsock_bind+0x66d/0x730
- vsock_bind+0x97/0xe0
- __sys_bind+0x154/0x1f0
- __x64_sys_bind+0x6e/0xb0
- do_syscall_64+0x93/0x1b0
- entry_SYSCALL_64_after_hwframe+0x76/0x7e
-
-refcount_t: underflow; use-after-free.
-WARNING: CPU: 7 PID: 2057 at lib/refcount.c:28 refcount_warn_saturate+0xee/0x150
-RIP: 0010:refcount_warn_saturate+0xee/0x150
- vsock_remove_bound+0x187/0x1e0
- __vsock_release+0x383/0x4a0
- vsock_release+0x90/0x120
- __sock_release+0xa3/0x250
- sock_close+0x14/0x20
- __fput+0x359/0xa80
- task_work_run+0x107/0x1d0
- do_exit+0x847/0x2560
- do_group_exit+0xb8/0x250
- __x64_sys_exit_group+0x3a/0x50
- x64_sys_call+0xfec/0x14f0
- do_syscall_64+0x93/0x1b0
- entry_SYSCALL_64_after_hwframe+0x76/0x7e
-
-Fixes: c0cfa2d8a788 ("vsock: add multi-transports support")
-Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
-Signed-off-by: Michal Luczaj <mhal@rbox.co>
-Link: https://patch.msgid.link/20250128-vsock-transport-vs-autobind-v3-1-1cf57065b770@rbox.co
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/vmw_vsock/af_vsock.c | 8 ++++++--
- 1 file changed, 6 insertions(+), 2 deletions(-)
-
-diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
-index 7ad84c6c19c3e..a224769566589 100644
---- a/net/vmw_vsock/af_vsock.c
-+++ b/net/vmw_vsock/af_vsock.c
-@@ -336,7 +336,10 @@ EXPORT_SYMBOL_GPL(vsock_find_connected_socket);
- void vsock_remove_sock(struct vsock_sock *vsk)
- {
--      vsock_remove_bound(vsk);
-+      /* Transport reassignment must not remove the binding. */
-+      if (sock_flag(sk_vsock(vsk), SOCK_DEAD))
-+              vsock_remove_bound(vsk);
-+
-       vsock_remove_connected(vsk);
- }
- EXPORT_SYMBOL_GPL(vsock_remove_sock);
-@@ -821,12 +824,13 @@ static void __vsock_release(struct sock *sk, int level)
-        */
-       lock_sock_nested(sk, level);
-+      sock_orphan(sk);
-+
-       if (vsk->transport)
-               vsk->transport->release(vsk);
-       else if (sock_type_connectible(sk->sk_type))
-               vsock_remove_sock(vsk);
--      sock_orphan(sk);
-       sk->sk_shutdown = SHUTDOWN_MASK;
-       skb_queue_purge(&sk->sk_receive_queue);
--- 
-2.39.5
-
diff --git a/queue-6.1/vsock-support-sockmap.patch b/queue-6.1/vsock-support-sockmap.patch
deleted file mode 100644 (file)
index e5060a9..0000000
+++ /dev/null
@@ -1,524 +0,0 @@
-From 97555d996913bcb2fe19b9e57c856045aa05c737 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 27 Mar 2023 19:11:51 +0000
-Subject: vsock: support sockmap
-
-From: Bobby Eshleman <bobby.eshleman@bytedance.com>
-
-[ Upstream commit 634f1a7110b439c65fd8a809171c1d2d28bcea6f ]
-
-This patch adds sockmap support for vsock sockets. It is intended to be
-usable by all transports, but only the virtio and loopback transports
-are implemented.
-
-SOCK_STREAM, SOCK_DGRAM, and SOCK_SEQPACKET are all supported.
-
-Signed-off-by: Bobby Eshleman <bobby.eshleman@bytedance.com>
-Acked-by: Michael S. Tsirkin <mst@redhat.com>
-Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Stable-dep-of: fcdd2242c023 ("vsock: Keep the binding until socket destruction")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/vhost/vsock.c                   |   1 +
- include/linux/virtio_vsock.h            |   1 +
- include/net/af_vsock.h                  |  17 +++
- net/vmw_vsock/Makefile                  |   1 +
- net/vmw_vsock/af_vsock.c                |  64 ++++++++-
- net/vmw_vsock/virtio_transport.c        |   2 +
- net/vmw_vsock/virtio_transport_common.c |  25 ++++
- net/vmw_vsock/vsock_bpf.c               | 174 ++++++++++++++++++++++++
- net/vmw_vsock/vsock_loopback.c          |   2 +
- 9 files changed, 281 insertions(+), 6 deletions(-)
- create mode 100644 net/vmw_vsock/vsock_bpf.c
-
-diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
-index c00f5821d6ecb..3248612e3f1bb 100644
---- a/drivers/vhost/vsock.c
-+++ b/drivers/vhost/vsock.c
-@@ -439,6 +439,7 @@ static struct virtio_transport vhost_transport = {
-               .notify_send_post_enqueue = virtio_transport_notify_send_post_enqueue,
-               .notify_buffer_size       = virtio_transport_notify_buffer_size,
-+              .read_skb = virtio_transport_read_skb,
-       },
-       .send_pkt = vhost_transport_send_pkt,
-diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
-index 3f9c166113063..c58453699ee98 100644
---- a/include/linux/virtio_vsock.h
-+++ b/include/linux/virtio_vsock.h
-@@ -245,4 +245,5 @@ u32 virtio_transport_get_credit(struct virtio_vsock_sock *vvs, u32 wanted);
- void virtio_transport_put_credit(struct virtio_vsock_sock *vvs, u32 credit);
- void virtio_transport_deliver_tap_pkt(struct sk_buff *skb);
- int virtio_transport_purge_skbs(void *vsk, struct sk_buff_head *list);
-+int virtio_transport_read_skb(struct vsock_sock *vsk, skb_read_actor_t read_actor);
- #endif /* _LINUX_VIRTIO_VSOCK_H */
-diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
-index 568a87c5e0d0f..0e7504a42925f 100644
---- a/include/net/af_vsock.h
-+++ b/include/net/af_vsock.h
-@@ -75,6 +75,7 @@ struct vsock_sock {
-       void *trans;
- };
-+s64 vsock_connectible_has_data(struct vsock_sock *vsk);
- s64 vsock_stream_has_data(struct vsock_sock *vsk);
- s64 vsock_stream_has_space(struct vsock_sock *vsk);
- struct sock *vsock_create_connected(struct sock *parent);
-@@ -173,6 +174,9 @@ struct vsock_transport {
-       /* Addressing. */
-       u32 (*get_local_cid)(void);
-+
-+      /* Read a single skb */
-+      int (*read_skb)(struct vsock_sock *, skb_read_actor_t);
- };
- /**** CORE ****/
-@@ -225,5 +229,18 @@ int vsock_init_tap(void);
- int vsock_add_tap(struct vsock_tap *vt);
- int vsock_remove_tap(struct vsock_tap *vt);
- void vsock_deliver_tap(struct sk_buff *build_skb(void *opaque), void *opaque);
-+int vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
-+                            int flags);
-+int vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
-+                      size_t len, int flags);
-+
-+#ifdef CONFIG_BPF_SYSCALL
-+extern struct proto vsock_proto;
-+int vsock_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore);
-+void __init vsock_bpf_build_proto(void);
-+#else
-+static inline void __init vsock_bpf_build_proto(void)
-+{}
-+#endif
- #endif /* __AF_VSOCK_H__ */
-diff --git a/net/vmw_vsock/Makefile b/net/vmw_vsock/Makefile
-index 6a943ec95c4a5..5da74c4a9f1d1 100644
---- a/net/vmw_vsock/Makefile
-+++ b/net/vmw_vsock/Makefile
-@@ -8,6 +8,7 @@ obj-$(CONFIG_HYPERV_VSOCKETS) += hv_sock.o
- obj-$(CONFIG_VSOCKETS_LOOPBACK) += vsock_loopback.o
- vsock-y += af_vsock.o af_vsock_tap.o vsock_addr.o
-+vsock-$(CONFIG_BPF_SYSCALL) += vsock_bpf.o
- vsock_diag-y += diag.o
-diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
-index 88b5702a0a47c..e0107c873f261 100644
---- a/net/vmw_vsock/af_vsock.c
-+++ b/net/vmw_vsock/af_vsock.c
-@@ -118,10 +118,13 @@ static void vsock_sk_destruct(struct sock *sk);
- static int vsock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
- /* Protocol family. */
--static struct proto vsock_proto = {
-+struct proto vsock_proto = {
-       .name = "AF_VSOCK",
-       .owner = THIS_MODULE,
-       .obj_size = sizeof(struct vsock_sock),
-+#ifdef CONFIG_BPF_SYSCALL
-+      .psock_update_sk_prot = vsock_bpf_update_proto,
-+#endif
- };
- /* The default peer timeout indicates how long we will wait for a peer response
-@@ -880,7 +883,7 @@ s64 vsock_stream_has_data(struct vsock_sock *vsk)
- }
- EXPORT_SYMBOL_GPL(vsock_stream_has_data);
--static s64 vsock_connectible_has_data(struct vsock_sock *vsk)
-+s64 vsock_connectible_has_data(struct vsock_sock *vsk)
- {
-       struct sock *sk = sk_vsock(vsk);
-@@ -892,6 +895,7 @@ static s64 vsock_connectible_has_data(struct vsock_sock *vsk)
-       else
-               return vsock_stream_has_data(vsk);
- }
-+EXPORT_SYMBOL_GPL(vsock_connectible_has_data);
- s64 vsock_stream_has_space(struct vsock_sock *vsk)
- {
-@@ -1152,6 +1156,13 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
-       return mask;
- }
-+static int vsock_read_skb(struct sock *sk, skb_read_actor_t read_actor)
-+{
-+      struct vsock_sock *vsk = vsock_sk(sk);
-+
-+      return vsk->transport->read_skb(vsk, read_actor);
-+}
-+
- static int vsock_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
-                              size_t len)
- {
-@@ -1263,18 +1274,42 @@ static int vsock_dgram_connect(struct socket *sock,
-       memcpy(&vsk->remote_addr, remote_addr, sizeof(vsk->remote_addr));
-       sock->state = SS_CONNECTED;
-+      /* sock map disallows redirection of non-TCP sockets with sk_state !=
-+       * TCP_ESTABLISHED (see sock_map_redirect_allowed()), so we set
-+       * TCP_ESTABLISHED here to allow redirection of connected vsock dgrams.
-+       *
-+       * This doesn't seem to be abnormal state for datagram sockets, as the
-+       * same approach can be see in other datagram socket types as well
-+       * (such as unix sockets).
-+       */
-+      sk->sk_state = TCP_ESTABLISHED;
-+
- out:
-       release_sock(sk);
-       return err;
- }
--static int vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
--                             size_t len, int flags)
-+int vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
-+                      size_t len, int flags)
- {
--      struct vsock_sock *vsk = vsock_sk(sock->sk);
-+#ifdef CONFIG_BPF_SYSCALL
-+      const struct proto *prot;
-+#endif
-+      struct vsock_sock *vsk;
-+      struct sock *sk;
-+
-+      sk = sock->sk;
-+      vsk = vsock_sk(sk);
-+
-+#ifdef CONFIG_BPF_SYSCALL
-+      prot = READ_ONCE(sk->sk_prot);
-+      if (prot != &vsock_proto)
-+              return prot->recvmsg(sk, msg, len, flags, NULL);
-+#endif
-       return vsk->transport->dgram_dequeue(vsk, msg, len, flags);
- }
-+EXPORT_SYMBOL_GPL(vsock_dgram_recvmsg);
- static const struct proto_ops vsock_dgram_ops = {
-       .family = PF_VSOCK,
-@@ -1293,6 +1328,7 @@ static const struct proto_ops vsock_dgram_ops = {
-       .recvmsg = vsock_dgram_recvmsg,
-       .mmap = sock_no_mmap,
-       .sendpage = sock_no_sendpage,
-+      .read_skb = vsock_read_skb,
- };
- static int vsock_transport_cancel_pkt(struct vsock_sock *vsk)
-@@ -2106,13 +2142,16 @@ static int __vsock_seqpacket_recvmsg(struct sock *sk, struct msghdr *msg,
-       return err;
- }
--static int
-+int
- vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
-                         int flags)
- {
-       struct sock *sk;
-       struct vsock_sock *vsk;
-       const struct vsock_transport *transport;
-+#ifdef CONFIG_BPF_SYSCALL
-+      const struct proto *prot;
-+#endif
-       int err;
-       sk = sock->sk;
-@@ -2163,6 +2202,14 @@ vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
-               goto out;
-       }
-+#ifdef CONFIG_BPF_SYSCALL
-+      prot = READ_ONCE(sk->sk_prot);
-+      if (prot != &vsock_proto) {
-+              release_sock(sk);
-+              return prot->recvmsg(sk, msg, len, flags, NULL);
-+      }
-+#endif
-+
-       if (sk->sk_type == SOCK_STREAM)
-               err = __vsock_stream_recvmsg(sk, msg, len, flags);
-       else
-@@ -2172,6 +2219,7 @@ vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
-       release_sock(sk);
-       return err;
- }
-+EXPORT_SYMBOL_GPL(vsock_connectible_recvmsg);
- static int vsock_set_rcvlowat(struct sock *sk, int val)
- {
-@@ -2212,6 +2260,7 @@ static const struct proto_ops vsock_stream_ops = {
-       .mmap = sock_no_mmap,
-       .sendpage = sock_no_sendpage,
-       .set_rcvlowat = vsock_set_rcvlowat,
-+      .read_skb = vsock_read_skb,
- };
- static const struct proto_ops vsock_seqpacket_ops = {
-@@ -2233,6 +2282,7 @@ static const struct proto_ops vsock_seqpacket_ops = {
-       .recvmsg = vsock_connectible_recvmsg,
-       .mmap = sock_no_mmap,
-       .sendpage = sock_no_sendpage,
-+      .read_skb = vsock_read_skb,
- };
- static int vsock_create(struct net *net, struct socket *sock,
-@@ -2372,6 +2422,8 @@ static int __init vsock_init(void)
-               goto err_unregister_proto;
-       }
-+      vsock_bpf_build_proto();
-+
-       return 0;
- err_unregister_proto:
-diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
-index 5434c9f11d28d..21d1fad4ad0e2 100644
---- a/net/vmw_vsock/virtio_transport.c
-+++ b/net/vmw_vsock/virtio_transport.c
-@@ -458,6 +458,8 @@ static struct virtio_transport virtio_transport = {
-               .notify_send_pre_enqueue  = virtio_transport_notify_send_pre_enqueue,
-               .notify_send_post_enqueue = virtio_transport_notify_send_post_enqueue,
-               .notify_buffer_size       = virtio_transport_notify_buffer_size,
-+
-+              .read_skb = virtio_transport_read_skb,
-       },
-       .send_pkt = virtio_transport_send_pkt,
-diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
-index a65da57fe26fd..a713a21abf59c 100644
---- a/net/vmw_vsock/virtio_transport_common.c
-+++ b/net/vmw_vsock/virtio_transport_common.c
-@@ -1435,6 +1435,31 @@ int virtio_transport_purge_skbs(void *vsk, struct sk_buff_head *queue)
- }
- EXPORT_SYMBOL_GPL(virtio_transport_purge_skbs);
-+int virtio_transport_read_skb(struct vsock_sock *vsk, skb_read_actor_t recv_actor)
-+{
-+      struct virtio_vsock_sock *vvs = vsk->trans;
-+      struct sock *sk = sk_vsock(vsk);
-+      struct sk_buff *skb;
-+      int off = 0;
-+      int copied;
-+      int err;
-+
-+      spin_lock_bh(&vvs->rx_lock);
-+      /* Use __skb_recv_datagram() for race-free handling of the receive. It
-+       * works for types other than dgrams.
-+       */
-+      skb = __skb_recv_datagram(sk, &vvs->rx_queue, MSG_DONTWAIT, &off, &err);
-+      spin_unlock_bh(&vvs->rx_lock);
-+
-+      if (!skb)
-+              return err;
-+
-+      copied = recv_actor(sk, skb);
-+      kfree_skb(skb);
-+      return copied;
-+}
-+EXPORT_SYMBOL_GPL(virtio_transport_read_skb);
-+
- MODULE_LICENSE("GPL v2");
- MODULE_AUTHOR("Asias He");
- MODULE_DESCRIPTION("common code for virtio vsock");
-diff --git a/net/vmw_vsock/vsock_bpf.c b/net/vmw_vsock/vsock_bpf.c
-new file mode 100644
-index 0000000000000..a3c97546ab84a
---- /dev/null
-+++ b/net/vmw_vsock/vsock_bpf.c
-@@ -0,0 +1,174 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/* Copyright (c) 2022 Bobby Eshleman <bobby.eshleman@bytedance.com>
-+ *
-+ * Based off of net/unix/unix_bpf.c
-+ */
-+
-+#include <linux/bpf.h>
-+#include <linux/module.h>
-+#include <linux/skmsg.h>
-+#include <linux/socket.h>
-+#include <linux/wait.h>
-+#include <net/af_vsock.h>
-+#include <net/sock.h>
-+
-+#define vsock_sk_has_data(__sk, __psock)                              \
-+              ({      !skb_queue_empty(&(__sk)->sk_receive_queue) ||  \
-+                      !skb_queue_empty(&(__psock)->ingress_skb) ||    \
-+                      !list_empty(&(__psock)->ingress_msg);           \
-+              })
-+
-+static struct proto *vsock_prot_saved __read_mostly;
-+static DEFINE_SPINLOCK(vsock_prot_lock);
-+static struct proto vsock_bpf_prot;
-+
-+static bool vsock_has_data(struct sock *sk, struct sk_psock *psock)
-+{
-+      struct vsock_sock *vsk = vsock_sk(sk);
-+      s64 ret;
-+
-+      ret = vsock_connectible_has_data(vsk);
-+      if (ret > 0)
-+              return true;
-+
-+      return vsock_sk_has_data(sk, psock);
-+}
-+
-+static bool vsock_msg_wait_data(struct sock *sk, struct sk_psock *psock, long timeo)
-+{
-+      bool ret;
-+
-+      DEFINE_WAIT_FUNC(wait, woken_wake_function);
-+
-+      if (sk->sk_shutdown & RCV_SHUTDOWN)
-+              return true;
-+
-+      if (!timeo)
-+              return false;
-+
-+      add_wait_queue(sk_sleep(sk), &wait);
-+      sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
-+      ret = vsock_has_data(sk, psock);
-+      if (!ret) {
-+              wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
-+              ret = vsock_has_data(sk, psock);
-+      }
-+      sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
-+      remove_wait_queue(sk_sleep(sk), &wait);
-+      return ret;
-+}
-+
-+static int __vsock_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags)
-+{
-+      struct socket *sock = sk->sk_socket;
-+      int err;
-+
-+      if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)
-+              err = vsock_connectible_recvmsg(sock, msg, len, flags);
-+      else if (sk->sk_type == SOCK_DGRAM)
-+              err = vsock_dgram_recvmsg(sock, msg, len, flags);
-+      else
-+              err = -EPROTOTYPE;
-+
-+      return err;
-+}
-+
-+static int vsock_bpf_recvmsg(struct sock *sk, struct msghdr *msg,
-+                           size_t len, int flags, int *addr_len)
-+{
-+      struct sk_psock *psock;
-+      int copied;
-+
-+      psock = sk_psock_get(sk);
-+      if (unlikely(!psock))
-+              return __vsock_recvmsg(sk, msg, len, flags);
-+
-+      lock_sock(sk);
-+      if (vsock_has_data(sk, psock) && sk_psock_queue_empty(psock)) {
-+              release_sock(sk);
-+              sk_psock_put(sk, psock);
-+              return __vsock_recvmsg(sk, msg, len, flags);
-+      }
-+
-+      copied = sk_msg_recvmsg(sk, psock, msg, len, flags);
-+      while (copied == 0) {
-+              long timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
-+
-+              if (!vsock_msg_wait_data(sk, psock, timeo)) {
-+                      copied = -EAGAIN;
-+                      break;
-+              }
-+
-+              if (sk_psock_queue_empty(psock)) {
-+                      release_sock(sk);
-+                      sk_psock_put(sk, psock);
-+                      return __vsock_recvmsg(sk, msg, len, flags);
-+              }
-+
-+              copied = sk_msg_recvmsg(sk, psock, msg, len, flags);
-+      }
-+
-+      release_sock(sk);
-+      sk_psock_put(sk, psock);
-+
-+      return copied;
-+}
-+
-+/* Copy of original proto with updated sock_map methods */
-+static struct proto vsock_bpf_prot = {
-+      .close = sock_map_close,
-+      .recvmsg = vsock_bpf_recvmsg,
-+      .sock_is_readable = sk_msg_is_readable,
-+      .unhash = sock_map_unhash,
-+};
-+
-+static void vsock_bpf_rebuild_protos(struct proto *prot, const struct proto *base)
-+{
-+      *prot        = *base;
-+      prot->close  = sock_map_close;
-+      prot->recvmsg = vsock_bpf_recvmsg;
-+      prot->sock_is_readable = sk_msg_is_readable;
-+}
-+
-+static void vsock_bpf_check_needs_rebuild(struct proto *ops)
-+{
-+      /* Paired with the smp_store_release() below. */
-+      if (unlikely(ops != smp_load_acquire(&vsock_prot_saved))) {
-+              spin_lock_bh(&vsock_prot_lock);
-+              if (likely(ops != vsock_prot_saved)) {
-+                      vsock_bpf_rebuild_protos(&vsock_bpf_prot, ops);
-+                      /* Make sure proto function pointers are updated before publishing the
-+                       * pointer to the struct.
-+                       */
-+                      smp_store_release(&vsock_prot_saved, ops);
-+              }
-+              spin_unlock_bh(&vsock_prot_lock);
-+      }
-+}
-+
-+int vsock_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
-+{
-+      struct vsock_sock *vsk;
-+
-+      if (restore) {
-+              sk->sk_write_space = psock->saved_write_space;
-+              sock_replace_proto(sk, psock->sk_proto);
-+              return 0;
-+      }
-+
-+      vsk = vsock_sk(sk);
-+      if (!vsk->transport)
-+              return -ENODEV;
-+
-+      if (!vsk->transport->read_skb)
-+              return -EOPNOTSUPP;
-+
-+      vsock_bpf_check_needs_rebuild(psock->sk_proto);
-+      sock_replace_proto(sk, &vsock_bpf_prot);
-+      return 0;
-+}
-+
-+void __init vsock_bpf_build_proto(void)
-+{
-+      vsock_bpf_rebuild_protos(&vsock_bpf_prot, &vsock_proto);
-+}
-diff --git a/net/vmw_vsock/vsock_loopback.c b/net/vmw_vsock/vsock_loopback.c
-index 89905c092645a..e3afc0c866f55 100644
---- a/net/vmw_vsock/vsock_loopback.c
-+++ b/net/vmw_vsock/vsock_loopback.c
-@@ -91,6 +91,8 @@ static struct virtio_transport loopback_transport = {
-               .notify_send_pre_enqueue  = virtio_transport_notify_send_pre_enqueue,
-               .notify_send_post_enqueue = virtio_transport_notify_send_post_enqueue,
-               .notify_buffer_size       = virtio_transport_notify_buffer_size,
-+
-+              .read_skb = virtio_transport_read_skb,
-       },
-       .send_pkt = vsock_loopback_send_pkt,
--- 
-2.39.5
-