From owner-svn-src-head@freebsd.org Tue Aug 14 17:26:08 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id AA7B1107F0BE; Tue, 14 Aug 2018 17:26:08 +0000 (UTC) (envelope-from jtl@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 821D67C818; Tue, 14 Aug 2018 17:26:08 +0000 (UTC) (envelope-from jtl@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 605471E9C6; Tue, 14 Aug 2018 17:26:08 +0000 (UTC) (envelope-from jtl@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w7EHQ898016820; Tue, 14 Aug 2018 17:26:08 GMT (envelope-from jtl@FreeBSD.org) Received: (from jtl@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w7EHQ7aj016815; Tue, 14 Aug 2018 17:26:07 GMT (envelope-from jtl@FreeBSD.org) Message-Id: <201808141726.w7EHQ7aj016815@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jtl set sender to jtl@FreeBSD.org using -f From: "Jonathan T. Looney" Date: Tue, 14 Aug 2018 17:26:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r337782 - head/sys/netinet6 X-SVN-Group: head X-SVN-Commit-Author: jtl X-SVN-Commit-Paths: head/sys/netinet6 X-SVN-Commit-Revision: 337782 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Aug 2018 17:26:09 -0000 Author: jtl Date: Tue Aug 14 17:26:07 2018 New Revision: 337782 URL: https://svnweb.freebsd.org/changeset/base/337782 Log: Add a limit of the number of fragments per IPv6 packet. The IPv4 fragment reassembly code supports a limit on the number of fragments per packet. The default limit is currently 17 fragments. Among other things, this limit serves to limit the number of fragments the code must parse when trying to reassembly a packet. Add a limit to the IPv6 reassembly code. By default, limit a packet to 65 fragments (64 on the queue, plus one final fragment to complete the packet). This allows an average fragment size of 1,008 bytes, which should be sufficient to hold a fragment. (Recall that the IPv6 minimum MTU is 1280 bytes. Therefore, this configuration allows a full-size IPv6 packet to be fragmented on a link with the minimum MTU and still carry approximately 272 bytes of headers before the fragmented portion of the packet.) Users can adjust this limit using the net.inet6.ip6.maxfragsperpacket sysctl. Reviewed by: jhb Security: FreeBSD-SA-18:10.ip Security: CVE-2018-6923 Modified: head/sys/netinet6/frag6.c head/sys/netinet6/in6.h head/sys/netinet6/in6_proto.c head/sys/netinet6/ip6_var.h Modified: head/sys/netinet6/frag6.c ============================================================================== --- head/sys/netinet6/frag6.c Tue Aug 14 17:24:26 2018 (r337781) +++ head/sys/netinet6/frag6.c Tue Aug 14 17:26:07 2018 (r337782) @@ -136,6 +136,7 @@ frag6_init(void) mtx_init(&V_ip6q[i].lock, "ip6qlock", NULL, MTX_DEF); } V_ip6q_hashseed = arc4random(); + V_ip6_maxfragsperpacket = 64; if (!IS_DEFAULT_VNET(curvnet)) return; @@ -533,6 +534,7 @@ insert: /* * Stick new segment in its place; * check for complete reassembly. + * If not complete, check fragment limit. * Move to front of packet queue, as we are * the most recently active fragmented packet. */ @@ -549,12 +551,20 @@ insert: for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6; af6 = af6->ip6af_down) { if (af6->ip6af_off != next) { + if (q6->ip6q_nfrag > V_ip6_maxfragsperpacket) { + IP6STAT_INC(ip6s_fragdropped); + frag6_freef(q6, hash); + } IP6Q_UNLOCK(hash); return IPPROTO_DONE; } next += af6->ip6af_frglen; } if (af6->ip6af_up->ip6af_mff) { + if (q6->ip6q_nfrag > V_ip6_maxfragsperpacket) { + IP6STAT_INC(ip6s_fragdropped); + frag6_freef(q6, hash); + } IP6Q_UNLOCK(hash); return IPPROTO_DONE; } Modified: head/sys/netinet6/in6.h ============================================================================== --- head/sys/netinet6/in6.h Tue Aug 14 17:24:26 2018 (r337781) +++ head/sys/netinet6/in6.h Tue Aug 14 17:26:07 2018 (r337782) @@ -642,7 +642,8 @@ struct ip6_mtuinfo { #define IPV6CTL_INTRQMAXLEN 51 /* max length of IPv6 netisr queue */ #define IPV6CTL_INTRDQMAXLEN 52 /* max length of direct IPv6 netisr * queue */ -#define IPV6CTL_MAXID 53 +#define IPV6CTL_MAXFRAGSPERPACKET 53 /* Max fragments per packet */ +#define IPV6CTL_MAXID 54 #endif /* __BSD_VISIBLE */ /* Modified: head/sys/netinet6/in6_proto.c ============================================================================== --- head/sys/netinet6/in6_proto.c Tue Aug 14 17:24:26 2018 (r337781) +++ head/sys/netinet6/in6_proto.c Tue Aug 14 17:26:07 2018 (r337782) @@ -386,6 +386,7 @@ VNET_DEFINE(int, ip6_norbit_raif) = 0; VNET_DEFINE(int, ip6_rfc6204w3) = 0; VNET_DEFINE(int, ip6_maxfragpackets); /* initialized in frag6.c:frag6_init() */ int ip6_maxfrags; /* initialized in frag6.c:frag6_init() */ +VNET_DEFINE(int, ip6_maxfragsperpacket); /* initialized in frag6.c:frag6_init() */ VNET_DEFINE(int, ip6_log_interval) = 5; VNET_DEFINE(int, ip6_hdrnestlimit) = 15;/* How many header options will we * process? */ @@ -563,6 +564,9 @@ SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGS, maxfrags, "Maximum allowed number of outstanding IPv6 packet fragments. " "A value of 0 means no fragmented packets will be accepted, while a " "a value of -1 means no limit"); +SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGSPERPACKET, maxfragsperpacket, + CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_maxfragsperpacket), 0, + "Maximum allowed number of fragments per packet"); SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MCAST_PMTU, mcast_pmtu, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_mcast_pmtu), 0, "Enable path MTU discovery for multicast packets"); Modified: head/sys/netinet6/ip6_var.h ============================================================================== --- head/sys/netinet6/ip6_var.h Tue Aug 14 17:24:26 2018 (r337781) +++ head/sys/netinet6/ip6_var.h Tue Aug 14 17:26:07 2018 (r337782) @@ -303,6 +303,7 @@ VNET_DECLARE(int, ip6_maxfragpackets); /* Maximum pack * queue */ extern int ip6_maxfrags; /* Maximum fragments in reassembly * queue */ +VNET_DECLARE(int, ip6_maxfragsperpacket); /* Maximum fragments per packet */ VNET_DECLARE(int, ip6_accept_rtadv); /* Acts as a host not a router */ VNET_DECLARE(int, ip6_no_radr); /* No defroute from RA */ VNET_DECLARE(int, ip6_norbit_raif); /* Disable R-bit in NA on RA @@ -317,6 +318,7 @@ VNET_DECLARE(int, ip6_dad_count); /* DupAddrDetectionT #define V_ip6_mrouter VNET(ip6_mrouter) #define V_ip6_sendredirects VNET(ip6_sendredirects) #define V_ip6_maxfragpackets VNET(ip6_maxfragpackets) +#define V_ip6_maxfragsperpacket VNET(ip6_maxfragsperpacket) #define V_ip6_accept_rtadv VNET(ip6_accept_rtadv) #define V_ip6_no_radr VNET(ip6_no_radr) #define V_ip6_norbit_raif VNET(ip6_norbit_raif)