Skip to content

Commit e3c674d

Browse files
atenartPaolo Abeni
authored andcommitted
tunnels: reset the GSO metadata before reusing the skb
If a GSO skb is sent through a Geneve tunnel and if Geneve options are added, the split GSO skb might not fit in the MTU anymore and an ICMP frag needed packet can be generated. In such case the ICMP packet might go through the segmentation logic (and dropped) later if it reaches a path were the GSO status is checked and segmentation is required. This is especially true when an OvS bridge is used with a Geneve tunnel attached to it. The following set of actions could lead to the ICMP packet being wrongfully segmented: 1. An skb is constructed by the TCP layer (e.g. gso_type SKB_GSO_TCPV4, segs >= 2). 2. The skb hits the OvS bridge where Geneve options are added by an OvS action before being sent through the tunnel. 3. When the skb is xmited in the tunnel, the split skb does not fit anymore in the MTU and iptunnel_pmtud_build_icmp is called to generate an ICMP fragmentation needed packet. This is done by reusing the original (GSO!) skb. The GSO metadata is not cleared. 4. The ICMP packet being sent back hits the OvS bridge again and because skb_is_gso returns true, it goes through queue_gso_packets... 5. ...where __skb_gso_segment is called. The skb is then dropped. 6. Note that in the above example on re-transmission the skb won't be a GSO one as it would be segmented (len > MSS) and the ICMP packet should go through. Fix this by resetting the GSO information before reusing an skb in iptunnel_pmtud_build_icmp and iptunnel_pmtud_build_icmpv6. Fixes: 4cb47a8 ("tunnels: PMTU discovery support for directly bridged IP packets") Reported-by: Adrian Moreno <[email protected]> Signed-off-by: Antoine Tenart <[email protected]> Reviewed-by: Stefano Brivio <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent bf59028 commit e3c674d

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

net/ipv4/ip_tunnel_core.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
206206
if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct iphdr)))
207207
return -EINVAL;
208208

209+
if (skb_is_gso(skb))
210+
skb_gso_reset(skb);
211+
209212
skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
210213
pskb_pull(skb, ETH_HLEN);
211214
skb_reset_network_header(skb);
@@ -300,6 +303,9 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
300303
if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct ipv6hdr)))
301304
return -EINVAL;
302305

306+
if (skb_is_gso(skb))
307+
skb_gso_reset(skb);
308+
303309
skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
304310
pskb_pull(skb, ETH_HLEN);
305311
skb_reset_network_header(skb);

0 commit comments

Comments
 (0)