From: Greg Kroah-Hartman Date: Tue, 10 Sep 2024 07:30:28 +0000 (+0200) Subject: 5.15-stable patches X-Git-Tag: v4.19.322~33 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b057d2a1cdbc22dcf4fc188fa2f594d00f6e2dbc;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: gso-fix-dodgy-bit-handling-for-gso_udp_l4.patch net-change-maximum-number-of-udp-segments-to-128.patch net-drop-bad-gso-csum_start-and-offset-in-virtio_net_hdr.patch net-more-strict-virtio_net_hdr_gso_udp_l4-validation.patch --- diff --git a/queue-5.15/gso-fix-dodgy-bit-handling-for-gso_udp_l4.patch b/queue-5.15/gso-fix-dodgy-bit-handling-for-gso_udp_l4.patch new file mode 100644 index 00000000000..830791a4232 --- /dev/null +++ b/queue-5.15/gso-fix-dodgy-bit-handling-for-gso_udp_l4.patch @@ -0,0 +1,61 @@ +From willemdebruijn.kernel@gmail.com Mon Sep 9 20:25:15 2024 +From: Willem de Bruijn +Date: Mon, 9 Sep 2024 14:22:47 -0400 +Subject: gso: fix dodgy bit handling for GSO_UDP_L4 +To: stable@vger.kernel.org +Cc: netdev@vger.kernel.org, gregkh@linuxfoundation.org, christian@theune.cc, mathieu.tortuyaux@gmail.com, Yan Zhai , Willem de Bruijn , Willem de Bruijn , Jason Wang , "David S. Miller" +Message-ID: <20240909182506.270136-4-willemdebruijn.kernel@gmail.com> + +From: Yan Zhai + +[ Upstream commit 9840036786d90cea11a90d1f30b6dc003b34ee67 ] + +Commit 1fd54773c267 ("udp: allow header check for dodgy GSO_UDP_L4 +packets.") checks DODGY bit for UDP, but for packets that can be fed +directly to the device after gso_segs reset, it actually falls through +to fragmentation: + +https://lore.kernel.org/all/CAJPywTKDdjtwkLVUW6LRA2FU912qcDmQOQGt2WaDo28KzYDg+A@mail.gmail.com/ + +This change restores the expected behavior of GSO_UDP_L4 packets. + +Fixes: 1fd54773c267 ("udp: allow header check for dodgy GSO_UDP_L4 packets.") +Suggested-by: Willem de Bruijn +Signed-off-by: Yan Zhai +Reviewed-by: Willem de Bruijn +Acked-by: Jason Wang +Signed-off-by: David S. Miller + +[5.15 stable: clean backport] +Signed-off-by: Willem de Bruijn +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/udp_offload.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -272,13 +272,20 @@ struct sk_buff *__udp_gso_segment(struct + __sum16 check; + __be16 newlen; + +- if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST) +- return __udp_gso_segment_list(gso_skb, features, is_ipv6); +- + mss = skb_shinfo(gso_skb)->gso_size; + if (gso_skb->len <= sizeof(*uh) + mss) + return ERR_PTR(-EINVAL); + ++ if (skb_gso_ok(gso_skb, features | NETIF_F_GSO_ROBUST)) { ++ /* Packet is from an untrusted source, reset gso_segs. */ ++ skb_shinfo(gso_skb)->gso_segs = DIV_ROUND_UP(gso_skb->len - sizeof(*uh), ++ mss); ++ return NULL; ++ } ++ ++ if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST) ++ return __udp_gso_segment_list(gso_skb, features, is_ipv6); ++ + skb_pull(gso_skb, sizeof(*uh)); + + /* clear destructor to avoid skb_segment assigning it to tail */ diff --git a/queue-5.15/net-change-maximum-number-of-udp-segments-to-128.patch b/queue-5.15/net-change-maximum-number-of-udp-segments-to-128.patch new file mode 100644 index 00000000000..efce3bae473 --- /dev/null +++ b/queue-5.15/net-change-maximum-number-of-udp-segments-to-128.patch @@ -0,0 +1,71 @@ +From stable+bounces-74079-greg=kroah.com@vger.kernel.org Mon Sep 9 20:25:31 2024 +From: Willem de Bruijn +Date: Mon, 9 Sep 2024 14:22:46 -0400 +Subject: net: change maximum number of UDP segments to 128 +To: stable@vger.kernel.org +Cc: netdev@vger.kernel.org, gregkh@linuxfoundation.org, christian@theune.cc, mathieu.tortuyaux@gmail.com, Yuri Benditovich , Willem de Bruijn , "David S. Miller" +Message-ID: <20240909182506.270136-3-willemdebruijn.kernel@gmail.com> + +From: Yuri Benditovich + +[ Upstream commit 1382e3b6a3500c245e5278c66d210c02926f804f ] + +The commit fc8b2a619469 +("net: more strict VIRTIO_NET_HDR_GSO_UDP_L4 validation") +adds check of potential number of UDP segments vs +UDP_MAX_SEGMENTS in linux/virtio_net.h. +After this change certification test of USO guest-to-guest +transmit on Windows driver for virtio-net device fails, +for example with packet size of ~64K and mss of 536 bytes. +In general the USO should not be more restrictive than TSO. +Indeed, in case of unreasonably small mss a lot of segments +can cause queue overflow and packet loss on the destination. +Limit of 128 segments is good for any practical purpose, +with minimal meaningful mss of 536 the maximal UDP packet will +be divided to ~120 segments. +The number of segments for UDP packets is validated vs +UDP_MAX_SEGMENTS also in udp.c (v4,v6), this does not affect +quest-to-guest path but does affect packets sent to host, for +example. +It is important to mention that UDP_MAX_SEGMENTS is kernel-only +define and not available to user mode socket applications. +In order to request MSS smaller than MTU the applications +just uses setsockopt with SOL_UDP and UDP_SEGMENT and there is +no limitations on socket API level. + +Fixes: fc8b2a619469 ("net: more strict VIRTIO_NET_HDR_GSO_UDP_L4 validation") +Signed-off-by: Yuri Benditovich +Reviewed-by: Willem de Bruijn +Signed-off-by: David S. Miller + +[5.15-stable: fix conflict with neighboring but unrelated code from + e2a4392b61f6 ("udp: introduce udp->udp_flags") +Signed-off-by: Willem de Bruijn +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/udp.h | 2 +- + tools/testing/selftests/net/udpgso.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/include/linux/udp.h ++++ b/include/linux/udp.h +@@ -94,7 +94,7 @@ struct udp_sock { + int forward_deficit; + }; + +-#define UDP_MAX_SEGMENTS (1 << 6UL) ++#define UDP_MAX_SEGMENTS (1 << 7UL) + + static inline struct udp_sock *udp_sk(const struct sock *sk) + { +--- a/tools/testing/selftests/net/udpgso.c ++++ b/tools/testing/selftests/net/udpgso.c +@@ -34,7 +34,7 @@ + #endif + + #ifndef UDP_MAX_SEGMENTS +-#define UDP_MAX_SEGMENTS (1 << 6UL) ++#define UDP_MAX_SEGMENTS (1 << 7UL) + #endif + + #define CONST_MTU_TEST 1500 diff --git a/queue-5.15/net-drop-bad-gso-csum_start-and-offset-in-virtio_net_hdr.patch b/queue-5.15/net-drop-bad-gso-csum_start-and-offset-in-virtio_net_hdr.patch new file mode 100644 index 00000000000..5dd4ccaee6f --- /dev/null +++ b/queue-5.15/net-drop-bad-gso-csum_start-and-offset-in-virtio_net_hdr.patch @@ -0,0 +1,153 @@ +From willemdebruijn.kernel@gmail.com Mon Sep 9 20:25:16 2024 +From: Willem de Bruijn +Date: Mon, 9 Sep 2024 14:22:48 -0400 +Subject: net: drop bad gso csum_start and offset in virtio_net_hdr +To: stable@vger.kernel.org +Cc: netdev@vger.kernel.org, gregkh@linuxfoundation.org, christian@theune.cc, mathieu.tortuyaux@gmail.com, Willem de Bruijn , Jakub Kicinski +Message-ID: <20240909182506.270136-5-willemdebruijn.kernel@gmail.com> + +From: Willem de Bruijn + +[ Upstream commit 89add40066f9ed9abe5f7f886fe5789ff7e0c50e ] + +Tighten csum_start and csum_offset checks in virtio_net_hdr_to_skb +for GSO packets. + +The function already checks that a checksum requested with +VIRTIO_NET_HDR_F_NEEDS_CSUM is in skb linear. But for GSO packets +this might not hold for segs after segmentation. + +Syzkaller demonstrated to reach this warning in skb_checksum_help + + offset = skb_checksum_start_offset(skb); + ret = -EINVAL; + if (WARN_ON_ONCE(offset >= skb_headlen(skb))) + +By injecting a TSO packet: + +WARNING: CPU: 1 PID: 3539 at net/core/dev.c:3284 skb_checksum_help+0x3d0/0x5b0 + ip_do_fragment+0x209/0x1b20 net/ipv4/ip_output.c:774 + ip_finish_output_gso net/ipv4/ip_output.c:279 [inline] + __ip_finish_output+0x2bd/0x4b0 net/ipv4/ip_output.c:301 + iptunnel_xmit+0x50c/0x930 net/ipv4/ip_tunnel_core.c:82 + ip_tunnel_xmit+0x2296/0x2c70 net/ipv4/ip_tunnel.c:813 + __gre_xmit net/ipv4/ip_gre.c:469 [inline] + ipgre_xmit+0x759/0xa60 net/ipv4/ip_gre.c:661 + __netdev_start_xmit include/linux/netdevice.h:4850 [inline] + netdev_start_xmit include/linux/netdevice.h:4864 [inline] + xmit_one net/core/dev.c:3595 [inline] + dev_hard_start_xmit+0x261/0x8c0 net/core/dev.c:3611 + __dev_queue_xmit+0x1b97/0x3c90 net/core/dev.c:4261 + packet_snd net/packet/af_packet.c:3073 [inline] + +The geometry of the bad input packet at tcp_gso_segment: + +[ 52.003050][ T8403] skb len=12202 headroom=244 headlen=12093 tailroom=0 +[ 52.003050][ T8403] mac=(168,24) mac_len=24 net=(192,52) trans=244 +[ 52.003050][ T8403] shinfo(txflags=0 nr_frags=1 gso(size=1552 type=3 segs=0)) +[ 52.003050][ T8403] csum(0x60000c7 start=199 offset=1536 +ip_summed=3 complete_sw=0 valid=0 level=0) + +Mitigate with stricter input validation. + +csum_offset: for GSO packets, deduce the correct value from gso_type. +This is already done for USO. Extend it to TSO. Let UFO be: +udp[46]_ufo_fragment ignores these fields and always computes the +checksum in software. + +csum_start: finding the real offset requires parsing to the transport +header. Do not add a parser, use existing segmentation parsing. Thanks +to SKB_GSO_DODGY, that also catches bad packets that are hw offloaded. +Again test both TSO and USO. Do not test UFO for the above reason, and +do not test UDP tunnel offload. + +GSO packet are almost always CHECKSUM_PARTIAL. USO packets may be +CHECKSUM_NONE since commit 10154dbded6d6 ("udp: Allow GSO transmit +from devices with no checksum offload"), but then still these fields +are initialized correctly in udp4_hwcsum/udp6_hwcsum_outgoing. So no +need to test for ip_summed == CHECKSUM_PARTIAL first. + +This revises an existing fix mentioned in the Fixes tag, which broke +small packets with GSO offload, as detected by kselftests. + +Link: https://syzkaller.appspot.com/bug?extid=e1db31216c789f552871 +Link: https://lore.kernel.org/netdev/20240723223109.2196886-1-kuba@kernel.org +Fixes: e269d79c7d35 ("net: missing check virtio") +Cc: stable@vger.kernel.org +Signed-off-by: Willem de Bruijn +Link: https://patch.msgid.link/20240729201108.1615114-1-willemdebruijn.kernel@gmail.com +Signed-off-by: Jakub Kicinski + +[5.15 stable: clean backport] +Signed-off-by: Willem de Bruijn +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/virtio_net.h | 16 +++++----------- + net/ipv4/tcp_offload.c | 3 +++ + net/ipv4/udp_offload.c | 4 ++++ + 3 files changed, 12 insertions(+), 11 deletions(-) + +--- a/include/linux/virtio_net.h ++++ b/include/linux/virtio_net.h +@@ -51,7 +51,6 @@ static inline int virtio_net_hdr_to_skb( + unsigned int thlen = 0; + unsigned int p_off = 0; + unsigned int ip_proto; +- u64 ret, remainder, gso_size; + + if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { + switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { +@@ -88,16 +87,6 @@ static inline int virtio_net_hdr_to_skb( + u32 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); + u32 needed = start + max_t(u32, thlen, off + sizeof(__sum16)); + +- if (hdr->gso_size) { +- gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size); +- ret = div64_u64_rem(skb->len, gso_size, &remainder); +- if (!(ret && (hdr->gso_size > needed) && +- ((remainder > needed) || (remainder == 0)))) { +- return -EINVAL; +- } +- skb_shinfo(skb)->tx_flags |= SKBFL_SHARED_FRAG; +- } +- + if (!pskb_may_pull(skb, needed)) + return -EINVAL; + +@@ -170,6 +159,11 @@ retry: + if (gso_type != SKB_GSO_UDP_L4) + return -EINVAL; + break; ++ case SKB_GSO_TCPV4: ++ case SKB_GSO_TCPV6: ++ if (skb->csum_offset != offsetof(struct tcphdr, check)) ++ return -EINVAL; ++ break; + } + + /* Kernel has a special handling for GSO_BY_FRAGS. */ +--- a/net/ipv4/tcp_offload.c ++++ b/net/ipv4/tcp_offload.c +@@ -71,6 +71,9 @@ struct sk_buff *tcp_gso_segment(struct s + if (thlen < sizeof(*th)) + goto out; + ++ if (unlikely(skb_checksum_start(skb) != skb_transport_header(skb))) ++ goto out; ++ + if (!pskb_may_pull(skb, thlen)) + goto out; + +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -276,6 +276,10 @@ struct sk_buff *__udp_gso_segment(struct + if (gso_skb->len <= sizeof(*uh) + mss) + return ERR_PTR(-EINVAL); + ++ if (unlikely(skb_checksum_start(gso_skb) != ++ skb_transport_header(gso_skb))) ++ return ERR_PTR(-EINVAL); ++ + if (skb_gso_ok(gso_skb, features | NETIF_F_GSO_ROBUST)) { + /* Packet is from an untrusted source, reset gso_segs. */ + skb_shinfo(gso_skb)->gso_segs = DIV_ROUND_UP(gso_skb->len - sizeof(*uh), diff --git a/queue-5.15/net-more-strict-virtio_net_hdr_gso_udp_l4-validation.patch b/queue-5.15/net-more-strict-virtio_net_hdr_gso_udp_l4-validation.patch new file mode 100644 index 00000000000..c0a36ccf6ae --- /dev/null +++ b/queue-5.15/net-more-strict-virtio_net_hdr_gso_udp_l4-validation.patch @@ -0,0 +1,89 @@ +From stable+bounces-74078-greg=kroah.com@vger.kernel.org Mon Sep 9 20:25:27 2024 +From: Willem de Bruijn +Date: Mon, 9 Sep 2024 14:22:45 -0400 +Subject: net: more strict VIRTIO_NET_HDR_GSO_UDP_L4 validation +To: stable@vger.kernel.org +Cc: netdev@vger.kernel.org, gregkh@linuxfoundation.org, christian@theune.cc, mathieu.tortuyaux@gmail.com, Willem de Bruijn , syzbot+01cdbc31e9c0ae9b33ac@syzkaller.appspotmail.com, syzbot+c99d835ff081ca30f986@syzkaller.appspotmail.com, Eric Dumazet , Jason Wang , "David S. Miller" +Message-ID: <20240909182506.270136-2-willemdebruijn.kernel@gmail.com> + +From: Willem de Bruijn + +[ Upstream commit fc8b2a619469378717e7270d2a4e1ef93c585f7a ] + +Syzbot reported two new paths to hit an internal WARNING using the +new virtio gso type VIRTIO_NET_HDR_GSO_UDP_L4. + + RIP: 0010:skb_checksum_help+0x4a2/0x600 net/core/dev.c:3260 + skb len=64521 gso_size=344 +and + + RIP: 0010:skb_warn_bad_offload+0x118/0x240 net/core/dev.c:3262 + +Older virtio types have historically had loose restrictions, leading +to many entirely impractical fuzzer generated packets causing +problems deep in the kernel stack. Ideally, we would have had strict +validation for all types from the start. + +New virtio types can have tighter validation. Limit UDP GSO packets +inserted via virtio to the same limits imposed by the UDP_SEGMENT +socket interface: + +1. must use checksum offload +2. checksum offload matches UDP header +3. no more segments than UDP_MAX_SEGMENTS +4. UDP GSO does not take modifier flags, notably SKB_GSO_TCP_ECN + +Fixes: 860b7f27b8f7 ("linux/virtio_net.h: Support USO offload in vnet header.") +Reported-by: syzbot+01cdbc31e9c0ae9b33ac@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/0000000000005039270605eb0b7f@google.com/ +Reported-by: syzbot+c99d835ff081ca30f986@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/0000000000005426680605eb0b9f@google.com/ +Signed-off-by: Willem de Bruijn +Reviewed-by: Eric Dumazet +Acked-by: Jason Wang +Signed-off-by: David S. Miller + +[5.15 stable: clean backport] +Signed-off-by: Willem de Bruijn +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/virtio_net.h | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +--- a/include/linux/virtio_net.h ++++ b/include/linux/virtio_net.h +@@ -3,8 +3,8 @@ + #define _LINUX_VIRTIO_NET_H + + #include ++#include + #include +-#include + #include + + static inline bool virtio_net_hdr_match_proto(__be16 protocol, __u8 gso_type) +@@ -155,9 +155,22 @@ retry: + unsigned int nh_off = p_off; + struct skb_shared_info *shinfo = skb_shinfo(skb); + +- /* UFO may not include transport header in gso_size. */ +- if (gso_type & SKB_GSO_UDP) ++ switch (gso_type & ~SKB_GSO_TCP_ECN) { ++ case SKB_GSO_UDP: ++ /* UFO may not include transport header in gso_size. */ + nh_off -= thlen; ++ break; ++ case SKB_GSO_UDP_L4: ++ if (!(hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM)) ++ return -EINVAL; ++ if (skb->csum_offset != offsetof(struct udphdr, check)) ++ return -EINVAL; ++ if (skb->len - p_off > gso_size * UDP_MAX_SEGMENTS) ++ return -EINVAL; ++ if (gso_type != SKB_GSO_UDP_L4) ++ return -EINVAL; ++ break; ++ } + + /* Kernel has a special handling for GSO_BY_FRAGS. */ + if (gso_size == GSO_BY_FRAGS) diff --git a/queue-5.15/series b/queue-5.15/series index 8a5a1fef414..236d6ffcb40 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -204,3 +204,7 @@ asoc-sunxi-sun4i-i2s-fix-lrclk-polarity-in-i2s-mode.patch drm-i915-fence-mark-debug_fence_init_onstack-with-__.patch drm-i915-fence-mark-debug_fence_free-with-__maybe_un.patch gpio-rockchip-fix-of-node-leak-in-probe.patch +net-more-strict-virtio_net_hdr_gso_udp_l4-validation.patch +net-change-maximum-number-of-udp-segments-to-128.patch +gso-fix-dodgy-bit-handling-for-gso_udp_l4.patch +net-drop-bad-gso-csum_start-and-offset-in-virtio_net_hdr.patch