aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKornel Dulęba <kd@FreeBSD.org>2022-07-20 07:22:34 +0000
committerKornel Dulęba <kd@FreeBSD.org>2022-07-27 14:09:56 +0000
commit82042465c3b5477fc4f44be36077eab11b6b511b (patch)
treebfe4bb069987c2d44c8021f2202f7d6c04a2bfdb
parentd2c0ec8d19da6531676af82461e7a8247228f8f4 (diff)
downloadsrc-82042465c3b5477fc4f44be36077eab11b6b511b.tar.gz
src-82042465c3b5477fc4f44be36077eab11b6b511b.zip
icmp6: Improve validation of PMTU
Currently we accept any pmtu between IPV6_MMTU(1280B) and the link mtu. In some network topologies could allow a bad actor to perform a DOS attack. Contrary to IPv4 in IPv6 oversized packets are dropped, and a ICMP PACKET_TOO_BIG message is sent back to the sender. After receiving an ICMPv6 packet with pmtu bigger than the current one the victim will start sending frames that will be dropped a router with reduced MTU. Although it will eventually receive another message with correct pmtu, an attacker can still just inject their spoofed packets frequently enough to overwrite the correct value. This issue is described in detail in RFC8201, section 6. Fix this by checking the current pmtu, and accepting the new one only if it's smaller. Approved by: mw(mentor) Reviewed by: tuexen MFC after: 1 week Sponsored by: Stormshield Obtained from: Semihalf Differential Revision: https://reviews.freebsd.org/D35871
-rw-r--r--sys/netinet6/icmp6.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 3632f9396be0..832061ad9328 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -1111,6 +1111,7 @@ icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated)
struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */
u_int mtu = ntohl(icmp6->icmp6_mtu);
struct in_conninfo inc;
+ uint32_t max_mtu;
#if 0
/*
@@ -1151,7 +1152,11 @@ icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated)
if (in6_setscope(&inc.inc6_faddr, m->m_pkthdr.rcvif, NULL))
return;
- if (mtu < tcp_maxmtu6(&inc, NULL)) {
+ max_mtu = tcp_hc_getmtu(&inc);
+ if (max_mtu == 0)
+ max_mtu = tcp_maxmtu6(&inc, NULL);
+
+ if (mtu < max_mtu) {
tcp_hc_updatemtu(&inc, mtu);
ICMP6STAT_INC(icp6s_pmtuchg);
}