From: Greg Kroah-Hartman Date: Wed, 5 Feb 2025 12:58:52 +0000 (+0100) Subject: 6.1-stable patches X-Git-Tag: v6.6.76~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=065ae4a60ae247246598c7bf2b420ef48ee0a65c;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: pinctrl-stm32-fix-array-read-out-of-bound.patch --- 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 index cf4ee1efb1..0000000000 --- a/queue-6.1/bpf-vsock-invoke-proto-close-on-close.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 731abe55c67c849d2ca1122baa608711da2bda50 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 18 Nov 2024 22:03:43 +0100 -Subject: bpf, vsock: Invoke proto::close on close() - -From: Michal Luczaj - -[ 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 -Reviewed-by: Stefano Garzarella -Reviewed-by: Luigi Leonardi -Link: https://lore.kernel.org/r/20241118-vsock-bpf-poll-close-v1-3-f1b9669cacdc@rbox.co -Signed-off-by: Alexei Starovoitov -Acked-by: John Fastabend -Stable-dep-of: fcdd2242c023 ("vsock: Keep the binding until socket destruction") -Signed-off-by: Sasha Levin ---- - 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 index 0000000000..9ae22109cf --- /dev/null +++ b/queue-6.1/pinctrl-stm32-fix-array-read-out-of-bound.patch @@ -0,0 +1,41 @@ +From edd48fd9d45370d6c8ba0dd834fcc51ff688cc87 Mon Sep 17 00:00:00 2001 +From: Antonio Borneo +Date: Tue, 7 Nov 2023 12:05:20 +0100 +Subject: pinctrl: stm32: fix array read out of bound + +From: Antonio Borneo + +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 +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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++) { diff --git a/queue-6.1/series b/queue-6.1/series index 737c9837dd..d9fa968ac2 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -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 index 30ed7f6461..0000000000 --- a/queue-6.1/vsock-allow-retrying-on-connect-failure.patch +++ /dev/null @@ -1,45 +0,0 @@ -From d3a46a60470293c3ad53c23cb2ac32a8ae18e156 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 28 Jan 2025 14:15:28 +0100 -Subject: vsock: Allow retrying on connect() failure - -From: Michal Luczaj - -[ 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 -Reviewed-by: Luigi Leonardi -Signed-off-by: Michal Luczaj -Link: https://patch.msgid.link/20250128-vsock-transport-vs-autobind-v3-2-1cf57065b770@rbox.co -Signed-off-by: Jakub Kicinski -Signed-off-by: Sasha Levin ---- - 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 index 44531924a8..0000000000 --- a/queue-6.1/vsock-keep-the-binding-until-socket-destruction.patch +++ /dev/null @@ -1,136 +0,0 @@ -From dd8cb65af0ef10d3d6f6aca093a9d405bc6378f2 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 28 Jan 2025 14:15:27 +0100 -Subject: vsock: Keep the binding until socket destruction - -From: Michal Luczaj - -[ 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 -Signed-off-by: Michal Luczaj -Link: https://patch.msgid.link/20250128-vsock-transport-vs-autobind-v3-1-1cf57065b770@rbox.co -Signed-off-by: Jakub Kicinski -Signed-off-by: Sasha Levin ---- - 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 index e5060a9aca..0000000000 --- a/queue-6.1/vsock-support-sockmap.patch +++ /dev/null @@ -1,524 +0,0 @@ -From 97555d996913bcb2fe19b9e57c856045aa05c737 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 27 Mar 2023 19:11:51 +0000 -Subject: vsock: support sockmap - -From: Bobby Eshleman - -[ 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 -Acked-by: Michael S. Tsirkin -Reviewed-by: Stefano Garzarella -Signed-off-by: David S. Miller -Stable-dep-of: fcdd2242c023 ("vsock: Keep the binding until socket destruction") -Signed-off-by: Sasha Levin ---- - 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 -+ * -+ * Based off of net/unix/unix_bpf.c -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -