summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorZhiling Zou <zhilinz@nebusec.ai>2026-08-13 00:22:35 +0800
committerPaolo Abeni <pabeni@redhat.com>2026-08-18 12:42:30 +0200
commit6b222adeb9340306e2ff97127c76117abb9b3df8 (patch)
treed206ea9474975a6e5585fac0532153aa1a26a93d /include
parent505b6d296c486ef7d1274f279d4c43a172f63224 (diff)
downloadlinux-6b222adeb9340306e2ff97127c76117abb9b3df8.tar.gz
linux-6b222adeb9340306e2ff97127c76117abb9b3df8.zip
net: cap advertised IP tunnel headroom
IP tunnel devices derive their advertised needed_headroom from lower output devices. A stack of user-created devices can make the derived value larger than the 16-bit skb header offsets can represent. Once IP output reserves it, skb head expansion can wrap those offsets. The runtime transmit path already caps a growing needed_headroom at 512. Apply the same cap when tunnel configuration publishes needed_headroom derived from a lower output device. Capping the advertised value is safe: IP tunnel transmit still expands the skb when a packet needs more headroom. A nonsensical stacked configuration can therefore incur an extra reallocation, but it cannot publish an unbounded reservation to upper layers. Fixes: 1a37e412a022 ("net: Use 16bits for *_headers fields of struct skbuff") Cc: stable@vger.kernel.org Reported-by: Vega <vega@nebusec.ai> Signed-off-by: Zhiling Zou <zhilinz@nebusec.ai> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/ba04a1fd6bfae2377607fad5d8f80f7eb80fd4c4.1786542637.git.zhilinz@nebusec.ai Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'include')
-rw-r--r--include/net/ip_tunnels.h11
1 files changed, 9 insertions, 2 deletions
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index d708b66e55cd..85e3455cea25 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -629,8 +629,7 @@ 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)
+static inline unsigned int ip_tunnel_limit_headroom(unsigned int headroom)
{
/* we must cap headroom to some upperlimit, else pskb_expand_head
* will overflow header offsets in skb_headers_offset_update().
@@ -640,6 +639,14 @@ static inline void ip_tunnel_adj_headroom(struct net_device *dev,
if (headroom > max_allowed)
headroom = max_allowed;
+ return headroom;
+}
+
+static inline void ip_tunnel_adj_headroom(struct net_device *dev,
+ unsigned int headroom)
+{
+ headroom = ip_tunnel_limit_headroom(headroom);
+
if (headroom > READ_ONCE(dev->needed_headroom))
WRITE_ONCE(dev->needed_headroom, headroom);
}