Commit 50932307 authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski
Browse files

tunnels: do not assume transport header in iptunnel_pmtud_check_icmp()



In some cases, iptunnel_pmtud_check_icmp() can be called while
skb transport header is not set.

This triggers an out-of-bound access, because
(typeof(skb->transport_header))~0U is 65535.

Access the icmp header based on IPv4 network header,
after making sure icmp->type is present in skb linear part.

Note that iptunnel_pmtud_check_icmpv6()) is fine.

Fixes: 4cb47a86 ("tunnels: PMTU discovery support for directly bridged IP packets")
Reported-by: default avatarDamiano Melotti <melotti@google.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarKuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20260522115512.1519110-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 7d9ef0cb
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -280,7 +280,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
 */
static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
{
	const struct icmphdr *icmph = icmp_hdr(skb);
	const struct iphdr *iph = ip_hdr(skb);

	if (mtu < 576 || iph->frag_off != htons(IP_DF))
@@ -291,9 +290,17 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
	    ipv4_is_lbcast(iph->saddr)  || ipv4_is_multicast(iph->saddr))
		return 0;

	if (iph->protocol == IPPROTO_ICMP && icmp_is_err(icmph->type))
		return 0;
	if (iph->protocol == IPPROTO_ICMP) {
		const struct icmphdr *icmph;

		if (!pskb_network_may_pull(skb, iph->ihl * 4 +
						offsetofend(struct icmphdr, type)))
			return 0;
		iph = ip_hdr(skb);
		icmph = (void *)iph + iph->ihl * 4;
		if (icmp_is_err(icmph->type))
			return 0;
	}
	return iptunnel_pmtud_build_icmp(skb, mtu);
}