]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net/ip6_tunnel: Prevent perpetual tunnel growth
authorDmitry Safonov <dima@arista.com>
Thu, 9 Oct 2025 15:02:19 +0000 (16:02 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 29 Oct 2025 13:04:33 +0000 (14:04 +0100)
[ Upstream commit 21f4d45eba0b2dcae5dbc9e5e0ad08735c993f16 ]

Similarly to ipv4 tunnel, ipv6 version updates dev->needed_headroom, too.
While ipv4 tunnel headroom adjustment growth was limited in
commit 5ae1e9922bbd ("net: ip_tunnel: prevent perpetual headroom growth"),
ipv6 tunnel yet increases the headroom without any ceiling.

Reflect ipv4 tunnel headroom adjustment limit on ipv6 version.

Credits to Francesco Ruggeri, who was originally debugging this issue
and wrote local Arista-specific patch and a reproducer.

Fixes: 8eb30be0352d ("ipv6: Create ip6_tnl_xmit")
Cc: Florian Westphal <fw@strlen.de>
Cc: Francesco Ruggeri <fruggeri05@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Link: https://patch.msgid.link/20251009-ip6_tunnel-headroom-v2-1-8e4dbd8f7e35@arista.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/net/ip_tunnels.h
net/ipv4/ip_tunnel.c
net/ipv6/ip6_tunnel.c

index 84751313b8265764d31e536877348fe6a504c6d3..e93db837412b20d8d0e43b1857f2de006b41d728 100644 (file)
@@ -481,6 +481,21 @@ struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
 int skb_tunnel_check_pmtu(struct sk_buff *skb, struct dst_entry *encap_dst,
                          int headroom, bool reply);
 
+static inline void ip_tunnel_adj_headroom(struct net_device *dev,
+                                         unsigned int headroom)
+{
+       /* we must cap headroom to some upperlimit, else pskb_expand_head
+        * will overflow header offsets in skb_headers_offset_update().
+        */
+       const unsigned int max_allowed = 512;
+
+       if (headroom > max_allowed)
+               headroom = max_allowed;
+
+       if (headroom > READ_ONCE(dev->needed_headroom))
+               WRITE_ONCE(dev->needed_headroom, headroom);
+}
+
 int iptunnel_handle_offloads(struct sk_buff *skb, int gso_type_mask);
 
 static inline int iptunnel_pull_offloads(struct sk_buff *skb)
index 90e55b9979e69af380445a10e12e9bda0ab2dc60..dcf9e9c52a22a63b27320c036a514505400a6b8d 100644 (file)
@@ -567,20 +567,6 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
        return 0;
 }
 
-static void ip_tunnel_adj_headroom(struct net_device *dev, unsigned int headroom)
-{
-       /* we must cap headroom to some upperlimit, else pskb_expand_head
-        * will overflow header offsets in skb_headers_offset_update().
-        */
-       static const unsigned int max_allowed = 512;
-
-       if (headroom > max_allowed)
-               headroom = max_allowed;
-
-       if (headroom > READ_ONCE(dev->needed_headroom))
-               WRITE_ONCE(dev->needed_headroom, headroom);
-}
-
 void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
                       u8 proto, int tunnel_hlen)
 {
index 2a470c0c38aef2ebf6e1981b3caa7232e5d9997c..dfca22c6d345dc280e3e3fb050c821bc008cf90a 100644 (file)
@@ -1256,8 +1256,7 @@ route_lookup:
         */
        max_headroom = LL_RESERVED_SPACE(dst->dev) + sizeof(struct ipv6hdr)
                        + dst->header_len + t->hlen;
-       if (max_headroom > READ_ONCE(dev->needed_headroom))
-               WRITE_ONCE(dev->needed_headroom, max_headroom);
+       ip_tunnel_adj_headroom(dev, max_headroom);
 
        err = ip6_tnl_encap(skb, t, &proto, fl6);
        if (err)