Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 Aug 2018 18:06:59 +0000 (UTC)
From:      "Jonathan T. Looney" <jtl@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r337798 - stable/11/sys/netinet6
Message-ID:  <201808141806.w7EI6xqm038081@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jtl
Date: Tue Aug 14 18:06:59 2018
New Revision: 337798
URL: https://svnweb.freebsd.org/changeset/base/337798

Log:
  MFC r337782:
    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.
  
  Approved by:	so
  Security:	FreeBSD-SA-18:10.ip
  Security:	CVE-2018-6923

Modified:
  stable/11/sys/netinet6/frag6.c
  stable/11/sys/netinet6/in6.h
  stable/11/sys/netinet6/in6_proto.c
  stable/11/sys/netinet6/ip6_var.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet6/frag6.c
==============================================================================
--- stable/11/sys/netinet6/frag6.c	Tue Aug 14 17:59:42 2018	(r337797)
+++ stable/11/sys/netinet6/frag6.c	Tue Aug 14 18:06:59 2018	(r337798)
@@ -134,6 +134,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;
 
@@ -530,6 +531,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.
 	 */
@@ -546,12 +548,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: stable/11/sys/netinet6/in6.h
==============================================================================
--- stable/11/sys/netinet6/in6.h	Tue Aug 14 17:59:42 2018	(r337797)
+++ stable/11/sys/netinet6/in6.h	Tue Aug 14 18:06:59 2018	(r337798)
@@ -637,7 +637,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: stable/11/sys/netinet6/in6_proto.c
==============================================================================
--- stable/11/sys/netinet6/in6_proto.c	Tue Aug 14 17:59:42 2018	(r337797)
+++ stable/11/sys/netinet6/in6_proto.c	Tue Aug 14 18:06:59 2018	(r337798)
@@ -384,6 +384,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? */
@@ -561,6 +562,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: stable/11/sys/netinet6/ip6_var.h
==============================================================================
--- stable/11/sys/netinet6/ip6_var.h	Tue Aug 14 17:59:42 2018	(r337797)
+++ stable/11/sys/netinet6/ip6_var.h	Tue Aug 14 18:06:59 2018	(r337798)
@@ -298,6 +298,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
@@ -312,6 +313,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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808141806.w7EI6xqm038081>