aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2018-01-25 13:03:03 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-25 16:27:34 -0500
commitf15ca723c1ebe6c1a06bc95fda6b62cd87b44559 (patch)
treed81f5825fe96dbfc589b19561961814fed78b4fc
parent4ee806d51176ba7b8ff1efd81f271d7252e03a1d (diff)
net: don't call update_pmtu unconditionally
Some dst_ops (e.g. md_dst_ops)) doesn't set this handler. It may result to: "BUG: unable to handle kernel NULL pointer dereference at (null)" Let's add a helper to check if update_pmtu is available before calling it. Fixes: 52a589d51f10 ("geneve: update skb dst pmtu on tx path") Fixes: a93bf0ff4490 ("vxlan: update skb dst pmtu on tx path") CC: Roman Kapl <code@rkapl.cz> CC: Xin Long <lucien.xin@gmail.com> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c3
-rw-r--r--drivers/net/geneve.c4
-rw-r--r--drivers/net/vxlan.c6
-rw-r--r--include/net/dst.h8
-rw-r--r--net/ipv4/ip_tunnel.c3
-rw-r--r--net/ipv4/ip_vti.c2
-rw-r--r--net/ipv6/ip6_tunnel.c6
-rw-r--r--net/ipv6/ip6_vti.c2
-rw-r--r--net/ipv6/sit.c4
9 files changed, 20 insertions, 18 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 2c13123bfd69..71ea9e26666c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -1456,8 +1456,7 @@ void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
1456 struct ipoib_dev_priv *priv = ipoib_priv(dev); 1456 struct ipoib_dev_priv *priv = ipoib_priv(dev);
1457 int e = skb_queue_empty(&priv->cm.skb_queue); 1457 int e = skb_queue_empty(&priv->cm.skb_queue);
1458 1458
1459 if (skb_dst(skb)) 1459 skb_dst_update_pmtu(skb, mtu);
1460 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
1461 1460
1462 skb_queue_tail(&priv->cm.skb_queue, skb); 1461 skb_queue_tail(&priv->cm.skb_queue, skb);
1463 if (e) 1462 if (e)
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 0a48b3073d3d..64fda2e1040e 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -829,7 +829,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
829 int mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr) - 829 int mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr) -
830 GENEVE_BASE_HLEN - info->options_len - 14; 830 GENEVE_BASE_HLEN - info->options_len - 14;
831 831
832 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); 832 skb_dst_update_pmtu(skb, mtu);
833 } 833 }
834 834
835 sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); 835 sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
@@ -875,7 +875,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
875 int mtu = dst_mtu(dst) - sizeof(struct ipv6hdr) - 875 int mtu = dst_mtu(dst) - sizeof(struct ipv6hdr) -
876 GENEVE_BASE_HLEN - info->options_len - 14; 876 GENEVE_BASE_HLEN - info->options_len - 14;
877 877
878 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); 878 skb_dst_update_pmtu(skb, mtu);
879 } 879 }
880 880
881 sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); 881 sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 31f4b7911ef8..c3e34e3c82a7 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2158,8 +2158,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
2158 if (skb_dst(skb)) { 2158 if (skb_dst(skb)) {
2159 int mtu = dst_mtu(ndst) - VXLAN_HEADROOM; 2159 int mtu = dst_mtu(ndst) - VXLAN_HEADROOM;
2160 2160
2161 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, 2161 skb_dst_update_pmtu(skb, mtu);
2162 skb, mtu);
2163 } 2162 }
2164 2163
2165 tos = ip_tunnel_ecn_encap(tos, old_iph, skb); 2164 tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
@@ -2200,8 +2199,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
2200 if (skb_dst(skb)) { 2199 if (skb_dst(skb)) {
2201 int mtu = dst_mtu(ndst) - VXLAN6_HEADROOM; 2200 int mtu = dst_mtu(ndst) - VXLAN6_HEADROOM;
2202 2201
2203 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, 2202 skb_dst_update_pmtu(skb, mtu);
2204 skb, mtu);
2205 } 2203 }
2206 2204
2207 tos = ip_tunnel_ecn_encap(tos, old_iph, skb); 2205 tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
diff --git a/include/net/dst.h b/include/net/dst.h
index b091fd536098..d49d607dd2b3 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -521,4 +521,12 @@ static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
521} 521}
522#endif 522#endif
523 523
524static inline void skb_dst_update_pmtu(struct sk_buff *skb, u32 mtu)
525{
526 struct dst_entry *dst = skb_dst(skb);
527
528 if (dst && dst->ops->update_pmtu)
529 dst->ops->update_pmtu(dst, NULL, skb, mtu);
530}
531
524#endif /* _NET_DST_H */ 532#endif /* _NET_DST_H */
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 5ddb1cb52bd4..6d21068f9b55 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -520,8 +520,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
520 else 520 else
521 mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; 521 mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
522 522
523 if (skb_dst(skb)) 523 skb_dst_update_pmtu(skb, mtu);
524 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
525 524
526 if (skb->protocol == htons(ETH_P_IP)) { 525 if (skb->protocol == htons(ETH_P_IP)) {
527 if (!skb_is_gso(skb) && 526 if (!skb_is_gso(skb) &&
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 949f432a5f04..51b1669334fe 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -200,7 +200,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
200 200
201 mtu = dst_mtu(dst); 201 mtu = dst_mtu(dst);
202 if (skb->len > mtu) { 202 if (skb->len > mtu) {
203 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); 203 skb_dst_update_pmtu(skb, mtu);
204 if (skb->protocol == htons(ETH_P_IP)) { 204 if (skb->protocol == htons(ETH_P_IP)) {
205 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, 205 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
206 htonl(mtu)); 206 htonl(mtu));
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 9a7cf355bc8c..1ee5584c3555 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -642,8 +642,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
642 if (rel_info > dst_mtu(skb_dst(skb2))) 642 if (rel_info > dst_mtu(skb_dst(skb2)))
643 goto out; 643 goto out;
644 644
645 skb_dst(skb2)->ops->update_pmtu(skb_dst(skb2), NULL, skb2, 645 skb_dst_update_pmtu(skb2, rel_info);
646 rel_info);
647 } 646 }
648 647
649 icmp_send(skb2, rel_type, rel_code, htonl(rel_info)); 648 icmp_send(skb2, rel_type, rel_code, htonl(rel_info));
@@ -1131,8 +1130,7 @@ route_lookup:
1131 mtu = 576; 1130 mtu = 576;
1132 } 1131 }
1133 1132
1134 if (skb_dst(skb) && !t->parms.collect_md) 1133 skb_dst_update_pmtu(skb, mtu);
1135 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
1136 if (skb->len - t->tun_hlen - eth_hlen > mtu && !skb_is_gso(skb)) { 1134 if (skb->len - t->tun_hlen - eth_hlen > mtu && !skb_is_gso(skb)) {
1137 *pmtu = mtu; 1135 *pmtu = mtu;
1138 err = -EMSGSIZE; 1136 err = -EMSGSIZE;
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index dbb74f3c57a7..8c184f84f353 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -483,7 +483,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
483 483
484 mtu = dst_mtu(dst); 484 mtu = dst_mtu(dst);
485 if (!skb->ignore_df && skb->len > mtu) { 485 if (!skb->ignore_df && skb->len > mtu) {
486 skb_dst(skb)->ops->update_pmtu(dst, NULL, skb, mtu); 486 skb_dst_update_pmtu(skb, mtu);
487 487
488 if (skb->protocol == htons(ETH_P_IPV6)) { 488 if (skb->protocol == htons(ETH_P_IPV6)) {
489 if (mtu < IPV6_MIN_MTU) 489 if (mtu < IPV6_MIN_MTU)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index d7dc23c1b2ca..3873d3877135 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -934,8 +934,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
934 df = 0; 934 df = 0;
935 } 935 }
936 936
937 if (tunnel->parms.iph.daddr && skb_dst(skb)) 937 if (tunnel->parms.iph.daddr)
938 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); 938 skb_dst_update_pmtu(skb, mtu);
939 939
940 if (skb->len > mtu && !skb_is_gso(skb)) { 940 if (skb->len > mtu && !skb_is_gso(skb)) {
941 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); 941 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);