From 3671914cf9724c45652e9b115bbd2d180b2572e7 Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Wed, 24 Jun 2026 19:11:22 -0400 Subject: [PATCH] import UBI passt-0^20251210.gd04c480-5.el9_8 --- ...atagrams-when-RX-virtqueue-is-not-us.patch | 106 ++++++++++++++++ ...e-IPv6-if-explicit-IPv6-socket-probe.patch | 116 ++++++++++++++++++ SPECS/passt.spec | 7 +- 3 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 SOURCES/0019-udp_vu-Discard-datagrams-when-RX-virtqueue-is-not-us.patch create mode 100644 SOURCES/0020-conf-util-Disable-IPv6-if-explicit-IPv6-socket-probe.patch diff --git a/SOURCES/0019-udp_vu-Discard-datagrams-when-RX-virtqueue-is-not-us.patch b/SOURCES/0019-udp_vu-Discard-datagrams-when-RX-virtqueue-is-not-us.patch new file mode 100644 index 0000000..78d99ce --- /dev/null +++ b/SOURCES/0019-udp_vu-Discard-datagrams-when-RX-virtqueue-is-not-us.patch @@ -0,0 +1,106 @@ +From 116e08082c23c8f00e608bd7c7825aa068401e46 Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Wed, 7 Jan 2026 09:08:09 +0100 +Subject: [PATCH 19/20] udp_vu: Discard datagrams when RX virtqueue is not + usable + +During vhost-user device initialization, UDP datagrams may arrive on +listening sockets before the guest has enabled the RX virtqueue. + +When this happens, udp_vu_sock_recv() returns 0 without consuming +the datagram from the socket. The caller, udp_sock_fwd(), uses a +while loop with udp_peek_addr() to process pending datagrams. Since +the datagram remains in the socket buffer, udp_peek_addr() keeps +returning data available, causing a busy loop with 100% CPU usage. + +To avoid that, we need to discard the data when the virtqueue is not +ready. udp_buf_sock_to_tap() actually does the same as it reads data +with udp_sock_recv() and if fd_tap is not initialized tap_send_frames() +drops them. + +Fixes: 28997fcb29b5 ("vhost-user: add vhost-user") +Link: https://bugs.passt.top/show_bug.cgi?id=185 +Signed-off-by: Laurent Vivier +Reviewed-by: David Gibson +Signed-off-by: Stefano Brivio +(cherry picked from commit edac476e268e4a0c5759a32fea9c720056de6315) +--- + udp_vu.c | 32 ++++++++++++++++++++++---------- + 1 file changed, 22 insertions(+), 10 deletions(-) + +diff --git a/udp_vu.c b/udp_vu.c +index c30dcf9..3774d53 100644 +--- a/udp_vu.c ++++ b/udp_vu.c +@@ -65,7 +65,8 @@ static size_t udp_vu_hdrlen(bool v6) + * @v6: Set for IPv6 connections + * @dlen: Size of received data (output) + * +- * Return: number of iov entries used to store the datagram ++ * Return: number of iov entries used to store the datagram, 0 if the datagram ++ * was discarded because the virtqueue is not ready, -1 on error + */ + static int udp_vu_sock_recv(const struct ctx *c, struct vu_virtq *vq, int s, + bool v6, ssize_t *dlen) +@@ -77,6 +78,15 @@ static int udp_vu_sock_recv(const struct ctx *c, struct vu_virtq *vq, int s, + + ASSERT(!c->no_udp); + ++ if (!vu_queue_enabled(vq) || !vu_queue_started(vq)) { ++ debug("Got UDP packet, but RX virtqueue not usable yet"); ++ ++ if (recvmsg(s, &msg, MSG_DONTWAIT) < 0) ++ debug_perror("Failed to discard datagram"); ++ ++ return 0; ++ } ++ + /* compute L2 header length */ + hdrlen = udp_vu_hdrlen(v6); + +@@ -87,7 +97,7 @@ static int udp_vu_sock_recv(const struct ctx *c, struct vu_virtq *vq, int s, + sizeof(struct virtio_net_hdr_mrg_rxbuf), + NULL); + if (iov_cnt == 0) +- return 0; ++ return -1; + + /* reserve space for the headers */ + ASSERT(iov_vu[0].iov_len >= MAX(hdrlen, ETH_ZLEN)); +@@ -101,7 +111,7 @@ static int udp_vu_sock_recv(const struct ctx *c, struct vu_virtq *vq, int s, + *dlen = recvmsg(s, &msg, 0); + if (*dlen < 0) { + vu_queue_rewind(vq, iov_cnt); +- return 0; ++ return -1; + } + + /* restore the pointer to the headers address */ +@@ -216,15 +226,17 @@ void udp_vu_sock_to_tap(const struct ctx *c, int s, int n, flow_sidx_t tosidx) + int iov_used; + + iov_used = udp_vu_sock_recv(c, vq, s, v6, &dlen); +- if (iov_used <= 0) ++ if (iov_used < 0) + break; + +- udp_vu_prepare(c, toside, dlen); +- if (*c->pcap) { +- udp_vu_csum(toside, iov_used); +- pcap_iov(iov_vu, iov_used, +- sizeof(struct virtio_net_hdr_mrg_rxbuf)); ++ if (iov_used > 0) { ++ udp_vu_prepare(c, toside, dlen); ++ if (*c->pcap) { ++ udp_vu_csum(toside, iov_used); ++ pcap_iov(iov_vu, iov_used, ++ sizeof(struct virtio_net_hdr_mrg_rxbuf)); ++ } ++ vu_flush(vdev, vq, elem, iov_used); + } +- vu_flush(vdev, vq, elem, iov_used); + } + } +-- +2.47.1 + diff --git a/SOURCES/0020-conf-util-Disable-IPv6-if-explicit-IPv6-socket-probe.patch b/SOURCES/0020-conf-util-Disable-IPv6-if-explicit-IPv6-socket-probe.patch new file mode 100644 index 0000000..32bd583 --- /dev/null +++ b/SOURCES/0020-conf-util-Disable-IPv6-if-explicit-IPv6-socket-probe.patch @@ -0,0 +1,116 @@ +From e361a399f88c8cef26bd74df8259d45001d9aa44 Mon Sep 17 00:00:00 2001 +From: Stefano Brivio +Date: Mon, 8 Jun 2026 21:06:17 +0200 +Subject: [PATCH 20/20] conf, util: Disable IPv6 if explicit IPv6 socket probe + fails + +In https://bugs.passt.top/show_bug.cgi?id=188, I originally reported +that if IPv6 is disabled in the kernel (for example via command line +parameter ipv6.disable=1, or disabled in build configuration), and we +attempt to forward any port, we'll exit right away after failing to +set up dual-stack listening sockets. + +The original instance of that issue is now fixed for pasta by commit +75dcbc300bf0 ("pasta: Warn, disable matching IP version if not +supported, in local mode") together with the new implementation of +the rule forwarding table, starting from commit b223bec48213 ("fwd, +tcp, udp: Set up listening sockets based on forward table"), because +we first parse forwarding options, then probe for IPv6 support in the +target namespace (and disable IPv6 as a result), and finally bind +sockets once we already know that IPv6 support is disabled. + +But we don't do that when invoked as passt, because we have no target +namespace and hence no probing for IPv6 support whatsoever. + +Add IPv6 to the socket features we test in sock_probe_features(), and, +if we fail to create an IPv6 socket for whatever reason (which might +include security policies as well), disable IPv6 support altogether, +so that we won't attempt to use dual-stack sockets for port forwarding +either. + +Note that the probe comes without any sort of debug message, because +at this point we haven't parsed the configuration yet, and we would +therefore print that regardless of the selected logging level and +other options, including --ipv4-only, which would be rather confusing. +I doubt we'll miss this kind of message though, IPv6 support being +disabled is anyway obvious from the initial configuration dump. + +Reported-by: Chi Cuong HA +Reported-by: Romain Geissler +Link: https://bugs.passt.top/show_bug.cgi?id=188 +Fixes: 4ddd59bc6085 ("conf: Separate local mode for each IP version, don't enable disabled IP version") +Signed-off-by: Stefano Brivio +Reviewed-by: David Gibson +(cherry picked from commit e1a6d9ef626aa6dbcfeef97dbbab3bd69c35b4b1) +--- + conf.c | 6 ++++++ + passt.h | 2 ++ + util.c | 8 ++++++++ + 3 files changed, 16 insertions(+) + +diff --git a/conf.c b/conf.c +index fdc19e8..1af7753 100644 +--- a/conf.c ++++ b/conf.c +@@ -1515,6 +1515,9 @@ void conf(struct ctx *c, int argc, char **argv) + uid_t uid; + gid_t gid; + ++ if (c->no_ipv6) ++ v4_only = true; ++ + if (c->mode == MODE_PASTA) { + c->no_dhcp_dns = c->no_dhcp_dns_search = 1; + fwd_default = FWD_AUTO; +@@ -1919,6 +1922,9 @@ void conf(struct ctx *c, int argc, char **argv) + v6_only = false; + break; + case '6': ++ if (c->no_ipv6) ++ die("IPv6 not available but --ipv6-only given"); ++ + v6_only = true; + v4_only = false; + break; +diff --git a/passt.h b/passt.h +index 79d01dd..266563e 100644 +--- a/passt.h ++++ b/passt.h +@@ -205,6 +205,7 @@ struct ip6_ctx { + * @low_wmem: Low probed net.core.wmem_max + * @low_rmem: Low probed net.core.rmem_max + * @no_bindtodevice: Unprivileged SO_BINDTODEVICE not available ++ * @no_ipv6: IPv6 sockets not available + * @vdev: vhost-user device + * @device_state_fd: Device state migration channel + * @device_state_result: Device state migration result +@@ -283,6 +284,7 @@ struct ctx { + int low_wmem; + int low_rmem; + int no_bindtodevice; ++ bool no_ipv6; + + struct vu_dev *vdev; + +diff --git a/util.c b/util.c +index bfeb619..f4f8f85 100644 +--- a/util.c ++++ b/util.c +@@ -331,6 +331,14 @@ void sock_probe_features(struct ctx *c) + c->no_bindtodevice = 1; + } + ++ /* Check if IPv6 sockets are usable */ ++ close(s); ++ s = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); ++ if (s < 0) { ++ c->no_ipv6 = true; ++ return; ++ } ++ + close(s); + } + +-- +2.47.1 + diff --git a/SPECS/passt.spec b/SPECS/passt.spec index 9157c79..e4e2604 100644 --- a/SPECS/passt.spec +++ b/SPECS/passt.spec @@ -13,7 +13,7 @@ Name: passt Version: 0^20251210.gd04c480 -Release: 4%{?dist} +Release: 5%{?dist} Summary: User-mode networking daemons for virtual machines and namespaces License: GPL-2.0-or-later AND BSD-3-Clause Group: System Environment/Daemons @@ -38,6 +38,8 @@ Patch15: 0015-tcp-Re-introduce-inactivity-timeouts-based-on-a-cloc.patch Patch16: 0016-tcp-Extend-tcp_send_flag-to-send-TCP-keepalive-segme.patch Patch17: 0017-tcp-Send-TCP-keepalive-segments-after-a-period-of-ta.patch Patch18: 0018-tcp-Replace-send-buffer-boost-with-EPOLLOUT-monitori.patch +Patch19: 0019-udp_vu-Discard-datagrams-when-RX-virtqueue-is-not-us.patch +Patch20: 0020-conf-util-Disable-IPv6-if-explicit-IPv6-socket-probe.patch BuildRequires: gcc, make, git, checkpolicy, selinux-policy-devel Requires: (%{name}-selinux = %{version}-%{release} if selinux-policy-%{selinuxtype}) @@ -152,6 +154,9 @@ fi %{_datadir}/selinux/packages/%{selinuxtype}/passt-repair.pp %changelog +* Thu Jun 11 2026 Stefano Brivio - 0^20251210.gd04c480-5 +- Resolves: RHEL-184106 RHEL-183990 + * Tue Apr 21 2026 Stefano Brivio - 0^20251210.gd04c480-4 - Resolves: RHEL-169637 RHEL-169639 RHEL-169648