Skip to content

Commit 3cec192

Browse files
committed
Merge branch 'tunnel-shinfo'
Antoine Tenart says: ==================== net: do not modify the shared tunnel info when PMTU triggers an ICMP reply The series fixes an issue were a shared ip_tunnel_info is modified when PMTU triggers an ICMP reply in vxlan and geneve, making following packets in that flow to have a wrong destination address if the flow isn't updated. A detailled information is given in each of the two commits. This was tested manually with OVS and I ran the PTMU selftests with kmemleak enabled (all OK, none was skipped). ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents aa5a5b7 + 68c1a94 commit 3cec192

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

drivers/net/geneve.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -908,8 +908,16 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
908908

909909
info = skb_tunnel_info(skb);
910910
if (info) {
911-
info->key.u.ipv4.dst = fl4.saddr;
912-
info->key.u.ipv4.src = fl4.daddr;
911+
struct ip_tunnel_info *unclone;
912+
913+
unclone = skb_tunnel_info_unclone(skb);
914+
if (unlikely(!unclone)) {
915+
dst_release(&rt->dst);
916+
return -ENOMEM;
917+
}
918+
919+
unclone->key.u.ipv4.dst = fl4.saddr;
920+
unclone->key.u.ipv4.src = fl4.daddr;
913921
}
914922

915923
if (!pskb_may_pull(skb, ETH_HLEN)) {
@@ -993,8 +1001,16 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
9931001
struct ip_tunnel_info *info = skb_tunnel_info(skb);
9941002

9951003
if (info) {
996-
info->key.u.ipv6.dst = fl6.saddr;
997-
info->key.u.ipv6.src = fl6.daddr;
1004+
struct ip_tunnel_info *unclone;
1005+
1006+
unclone = skb_tunnel_info_unclone(skb);
1007+
if (unlikely(!unclone)) {
1008+
dst_release(dst);
1009+
return -ENOMEM;
1010+
}
1011+
1012+
unclone->key.u.ipv6.dst = fl6.saddr;
1013+
unclone->key.u.ipv6.src = fl6.daddr;
9981014
}
9991015

10001016
if (!pskb_may_pull(skb, ETH_HLEN)) {

drivers/net/vxlan.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2725,12 +2725,17 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
27252725
goto tx_error;
27262726
} else if (err) {
27272727
if (info) {
2728+
struct ip_tunnel_info *unclone;
27282729
struct in_addr src, dst;
27292730

2731+
unclone = skb_tunnel_info_unclone(skb);
2732+
if (unlikely(!unclone))
2733+
goto tx_error;
2734+
27302735
src = remote_ip.sin.sin_addr;
27312736
dst = local_ip.sin.sin_addr;
2732-
info->key.u.ipv4.src = src.s_addr;
2733-
info->key.u.ipv4.dst = dst.s_addr;
2737+
unclone->key.u.ipv4.src = src.s_addr;
2738+
unclone->key.u.ipv4.dst = dst.s_addr;
27342739
}
27352740
vxlan_encap_bypass(skb, vxlan, vxlan, vni, false);
27362741
dst_release(ndst);
@@ -2781,12 +2786,17 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
27812786
goto tx_error;
27822787
} else if (err) {
27832788
if (info) {
2789+
struct ip_tunnel_info *unclone;
27842790
struct in6_addr src, dst;
27852791

2792+
unclone = skb_tunnel_info_unclone(skb);
2793+
if (unlikely(!unclone))
2794+
goto tx_error;
2795+
27862796
src = remote_ip.sin6.sin6_addr;
27872797
dst = local_ip.sin6.sin6_addr;
2788-
info->key.u.ipv6.src = src;
2789-
info->key.u.ipv6.dst = dst;
2798+
unclone->key.u.ipv6.src = src;
2799+
unclone->key.u.ipv6.dst = dst;
27902800
}
27912801

27922802
vxlan_encap_bypass(skb, vxlan, vxlan, vni, false);

0 commit comments

Comments
 (0)