Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f15ca723 authored by Nicolas Dichtel's avatar Nicolas Dichtel Committed by David S. Miller
Browse files

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: 52a589d5 ("geneve: update skb dst pmtu on tx path")
Fixes: a93bf0ff ("vxlan: update skb dst pmtu on tx path")
CC: Roman Kapl <code@rkapl.cz>
CC: Xin Long <lucien.xin@gmail.com>
Signed-off-by: default avatarNicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4ee806d5
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -1456,8 +1456,7 @@ void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
	struct ipoib_dev_priv *priv = ipoib_priv(dev);
	int e = skb_queue_empty(&priv->cm.skb_queue);

	if (skb_dst(skb))
		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
	skb_dst_update_pmtu(skb, mtu);

	skb_queue_tail(&priv->cm.skb_queue, skb);
	if (e)
+2 −2
Original line number Diff line number Diff line
@@ -829,7 +829,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
		int mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr) -
			  GENEVE_BASE_HLEN - info->options_len - 14;

		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
		skb_dst_update_pmtu(skb, mtu);
	}

	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,
		int mtu = dst_mtu(dst) - sizeof(struct ipv6hdr) -
			  GENEVE_BASE_HLEN - info->options_len - 14;

		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
		skb_dst_update_pmtu(skb, mtu);
	}

	sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+2 −4
Original line number Diff line number Diff line
@@ -2158,8 +2158,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
		if (skb_dst(skb)) {
			int mtu = dst_mtu(ndst) - VXLAN_HEADROOM;

			skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL,
						       skb, mtu);
			skb_dst_update_pmtu(skb, mtu);
		}

		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,
		if (skb_dst(skb)) {
			int mtu = dst_mtu(ndst) - VXLAN6_HEADROOM;

			skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL,
						       skb, mtu);
			skb_dst_update_pmtu(skb, mtu);
		}

		tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
+8 −0
Original line number Diff line number Diff line
@@ -521,4 +521,12 @@ static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
}
#endif

static inline void skb_dst_update_pmtu(struct sk_buff *skb, u32 mtu)
{
	struct dst_entry *dst = skb_dst(skb);

	if (dst && dst->ops->update_pmtu)
		dst->ops->update_pmtu(dst, NULL, skb, mtu);
}

#endif /* _NET_DST_H */
+1 −2
Original line number Diff line number Diff line
@@ -520,8 +520,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
	else
		mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;

	if (skb_dst(skb))
		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
	skb_dst_update_pmtu(skb, mtu);

	if (skb->protocol == htons(ETH_P_IP)) {
		if (!skb_is_gso(skb) &&
Loading