svn commit: r355254 - in head/sys: netinet netinet6 netipsec

Bjoern A. Zeeb bz at FreeBSD.org
Sun Dec 1 00:22:07 UTC 2019


Author: bz
Date: Sun Dec  1 00:22:04 2019
New Revision: 355254
URL: https://svnweb.freebsd.org/changeset/base/355254

Log:
  Fix m_pullup() problem after removing PULLDOWN_TESTs and KAME EXT_*macros.
  
  r354748-354750 replaced the KAME macros with m_pulldown() calls.
  Contrary to the rest of the network stack m_len checks before m_pulldown()
  were not put in placed (see r354748).
  Put these m_len checks in place for now (to go along with the style of the
  network stack since the initial commits).  These are not put in for
  performance but to avoid an error scenario (even though it also will help
  performance at the moment as it avoid allocating an extra mbuf; not because
  of the unconditional function call).
  
  The observed error case went like this:
  (1) an mbuf with M_EXT arrives and we call m_pullup() unconditionally on it.
  (2) m_pullup() will call m_get() unless the requested length is larger than
  MHLEN (in which case it'll m_freem() the perfectly fine mbuf) and migrate the
  requested length of data and pkthdr into the new mbuf.
  (3) If m_get() succeeds, a further m_pullup() call going over MHLEN will fail.
  This was observed with failing auto-configuration as an RA packet of
  200 bytes exceeded MHLEN and the m_pullup() called from nd6_ra_input()
  dropped the mbuf.
  (Re-)adding the m_len checks before m_pullup() calls avoids this problems
  with mbufs using external storage for now.
  
  MFC after:	3 weeks
  Sponsored by:	Netflix

Modified:
  head/sys/netinet/ip_carp.c
  head/sys/netinet/tcp_input.c
  head/sys/netinet6/dest6.c
  head/sys/netinet6/frag6.c
  head/sys/netinet6/icmp6.c
  head/sys/netinet6/ip6_input.c
  head/sys/netinet6/ip6_mroute.c
  head/sys/netinet6/mld6.c
  head/sys/netinet6/nd6_nbr.c
  head/sys/netinet6/nd6_rtr.c
  head/sys/netinet6/route6.c
  head/sys/netinet6/sctp6_usrreq.c
  head/sys/netinet6/udp6_usrreq.c
  head/sys/netipsec/xform_ah.c
  head/sys/netipsec/xform_esp.c

Modified: head/sys/netinet/ip_carp.c
==============================================================================
--- head/sys/netinet/ip_carp.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet/ip_carp.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -566,12 +566,14 @@ carp6_input(struct mbuf **mp, int *offp, int proto)
 	}
 
 	/* verify that we have a complete carp packet */
-	len = m->m_len;
-	m = m_pullup(m, *offp + sizeof(*ch));
-	if (m == NULL) {
-		CARPSTATS_INC(carps_badlen);
-		CARP_DEBUG("%s: packet size %u too small\n", __func__, len);
-		return (IPPROTO_DONE);
+	if (m->m_len < *offp + sizeof(*ch)) {
+		len = m->m_len;
+		m = m_pullup(m, *offp + sizeof(*ch));
+		if (m == NULL) {
+			CARPSTATS_INC(carps_badlen);
+			CARP_DEBUG("%s: packet size %u too small\n", __func__, len);
+			return (IPPROTO_DONE);
+		}
 	}
 	ch = (struct carp_header *)(mtod(m, caddr_t) + *offp);
 

Modified: head/sys/netinet/tcp_input.c
==============================================================================
--- head/sys/netinet/tcp_input.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet/tcp_input.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -517,11 +517,13 @@ tcp6_input(struct mbuf **mp, int *offp, int proto)
 	struct ip6_hdr *ip6;
 
 	m = *mp;
-	m = m_pullup(m, *offp + sizeof(struct tcphdr));
-	if (m == NULL) {
-		*mp = m;
-		TCPSTAT_INC(tcps_rcvshort);
-		return (IPPROTO_DONE);
+	if (m->m_len < *offp + sizeof(struct tcphdr)) {
+		m = m_pullup(m, *offp + sizeof(struct tcphdr));
+		if (m == NULL) {
+			*mp = m;
+			TCPSTAT_INC(tcps_rcvshort);
+			return (IPPROTO_DONE);
+		}
 	}
 
 	/*
@@ -708,10 +710,12 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
 	if (off > sizeof (struct tcphdr)) {
 #ifdef INET6
 		if (isipv6) {
-			m = m_pullup(m, off0 + off);
-			if (m == NULL) {
-				TCPSTAT_INC(tcps_rcvshort);
-				return (IPPROTO_DONE);
+			if (m->m_len < off0 + off) {
+				m = m_pullup(m, off0 + off);
+				if (m == NULL) {
+					TCPSTAT_INC(tcps_rcvshort);
+					return (IPPROTO_DONE);
+				}
 			}
 			ip6 = mtod(m, struct ip6_hdr *);
 			th = (struct tcphdr *)((caddr_t)ip6 + off0);

Modified: head/sys/netinet6/dest6.c
==============================================================================
--- head/sys/netinet6/dest6.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet6/dest6.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -73,20 +73,24 @@ dest6_input(struct mbuf **mp, int *offp, int proto)
 	off = *offp;
 
 	/* Validation of the length of the header. */
-	m = m_pullup(m, off + sizeof(*dstopts));
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		*mp = m;
-		return (IPPROTO_DONE);
+	if (m->m_len < off + sizeof(*dstopts)) {
+		m = m_pullup(m, off + sizeof(*dstopts));
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			*mp = m;
+			return (IPPROTO_DONE);
+		}
 	}
 	dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off);
 	dstoptlen = (dstopts->ip6d_len + 1) << 3;
 
-	m = m_pullup(m, off + dstoptlen);
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		*mp = m;
-		return (IPPROTO_DONE);
+	if (m->m_len < off + dstoptlen) {
+		m = m_pullup(m, off + dstoptlen);
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			*mp = m;
+			return (IPPROTO_DONE);
+		}
 	}
 	dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off);
 	off += dstoptlen;

Modified: head/sys/netinet6/frag6.c
==============================================================================
--- head/sys/netinet6/frag6.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet6/frag6.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -389,11 +389,13 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
 
 	M_ASSERTPKTHDR(m);
 
-	m = m_pullup(m, offset + sizeof(struct ip6_frag));
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		*mp = NULL;
-		return (IPPROTO_DONE);
+	if (m->m_len < offset + sizeof(struct ip6_frag)) {
+		m = m_pullup(m, offset + sizeof(struct ip6_frag));
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			*mp = NULL;
+			return (IPPROTO_DONE);
+		}
 	}
 	ip6 = mtod(m, struct ip6_hdr *);
 

Modified: head/sys/netinet6/icmp6.c
==============================================================================
--- head/sys/netinet6/icmp6.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet6/icmp6.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -317,10 +317,12 @@ icmp6_error(struct mbuf *m, int type, int code, int pa
 	if (off >= 0 && nxt == IPPROTO_ICMPV6) {
 		struct icmp6_hdr *icp;
 
-		m = m_pullup(m, off + sizeof(struct icmp6_hdr));
-		if (m == NULL) {
-			IP6STAT_INC(ip6s_exthdrtoolong);
-			return;
+		if (m->m_len < off + sizeof(struct icmp6_hdr)) {
+			m = m_pullup(m, off + sizeof(struct icmp6_hdr));
+			if (m == NULL) {
+				IP6STAT_INC(ip6s_exthdrtoolong);
+				return;
+			}
 		}
 		oip6 = mtod(m, struct ip6_hdr *);
 		icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
@@ -401,11 +403,13 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
 	m = *mp;
 	off = *offp;
 
-	m = m_pullup(m, off + sizeof(struct icmp6_hdr));
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		*mp = m;
-		return (IPPROTO_DONE);
+	if (m->m_len < off + sizeof(struct icmp6_hdr)) {
+		m = m_pullup(m, off + sizeof(struct icmp6_hdr));
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			*mp = m;
+			return (IPPROTO_DONE);
+		}
 	}
 
 	/*
@@ -566,10 +570,12 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
 			n->m_pkthdr.len = n0len + (noff - off);
 			n->m_next = n0;
 		} else {
-			n = m_pullup(n, off + sizeof(*nicmp6));
-			if (n == NULL) {
-				IP6STAT_INC(ip6s_exthdrtoolong);
-				break;
+			if (n->m_len < off + sizeof(*nicmp6)) {
+				n = m_pullup(n, off + sizeof(*nicmp6));
+				if (n == NULL) {
+					IP6STAT_INC(ip6s_exthdrtoolong);
+					break;
+				}
 			}
 			nicmp6 = (struct icmp6_hdr *)(mtod(n, caddr_t) + off);
 			noff = off;
@@ -635,11 +641,14 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
 		if (pr == NULL)
 			pr = curthread->td_ucred->cr_prison;
 		if (mode == FQDN) {
-			m = m_pullup(m, off + sizeof(struct icmp6_nodeinfo));
-			if (m == NULL) {
-				IP6STAT_INC(ip6s_exthdrtoolong);
-				*mp = m;
-				return (IPPROTO_DONE);
+			if (m->m_len < off + sizeof(struct icmp6_nodeinfo)) {
+				m = m_pullup(m, off +
+				    sizeof(struct icmp6_nodeinfo));
+				if (m == NULL) {
+					IP6STAT_INC(ip6s_exthdrtoolong);
+					*mp = m;
+					return (IPPROTO_DONE);
+				}
 			}
 			n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
 			if (n)
@@ -725,11 +734,13 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
 		if (icmp6len < sizeof(struct nd_router_solicit))
 			goto badlen;
 		if (send_sendso_input_hook != NULL) {
-			m = m_pullup(m, off + icmp6len);
-			if (m == NULL) {
-				IP6STAT_INC(ip6s_exthdrtoolong);
-				*mp = NULL;
-				return (IPPROTO_DONE);
+			if (m->m_len < off + icmp6len) {
+				m = m_pullup(m, off + icmp6len);
+				if (m == NULL) {
+					IP6STAT_INC(ip6s_exthdrtoolong);
+					*mp = NULL;
+					return (IPPROTO_DONE);
+				}
 			}
 			error = send_sendso_input_hook(m, ifp, SND_IN, ip6len);
 			if (error == 0) {
@@ -891,11 +902,13 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp
 		goto freeit;
 	}
 
-	m = m_pullup(m, off + sizeof(*icmp6) + sizeof(struct ip6_hdr));
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		*mp = m;
-		return (-1);
+	if (m->m_len < off + sizeof(*icmp6) + sizeof(struct ip6_hdr)) {
+		m = m_pullup(m, off + sizeof(*icmp6) + sizeof(struct ip6_hdr));
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			*mp = m;
+			return (-1);
+		}
 	}
 	icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
 	eip6 = (struct ip6_hdr *)(icmp6 + 1);
@@ -921,11 +934,14 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp
 			case IPPROTO_HOPOPTS:
 			case IPPROTO_DSTOPTS:
 			case IPPROTO_AH:
-				m = m_pullup(m, eoff + sizeof(struct ip6_ext));
-				if (m == NULL) {
-					IP6STAT_INC(ip6s_exthdrtoolong);
-					*mp = m;
-					return (-1);
+				if (m->m_len < eoff + sizeof(struct ip6_ext)) {
+					m = m_pullup(m, eoff +
+					    sizeof(struct ip6_ext));
+					if (m == NULL) {
+						IP6STAT_INC(ip6s_exthdrtoolong);
+						*mp = m;
+						return (-1);
+					}
 				}
 				eh = (struct ip6_ext *)
 				    (mtod(m, caddr_t) + eoff);
@@ -944,11 +960,13 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp
 				 * information that depends on the final
 				 * destination (e.g. path MTU).
 				 */
-				m = m_pullup(m, eoff + sizeof(*rth));
-				if (m == NULL) {
-					IP6STAT_INC(ip6s_exthdrtoolong);
-					*mp = m;
-					return (-1);
+				if (m->m_len < eoff + sizeof(*rth)) {
+					m = m_pullup(m, eoff + sizeof(*rth));
+					if (m == NULL) {
+						IP6STAT_INC(ip6s_exthdrtoolong);
+						*mp = m;
+						return (-1);
+					}
 				}
 				rth = (struct ip6_rthdr *)
 				    (mtod(m, caddr_t) + eoff);
@@ -965,11 +983,14 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp
 				    rth->ip6r_type == IPV6_RTHDR_TYPE_0) {
 					int hops;
 
-					m = m_pullup(m, eoff + rthlen);
-					if (m == NULL) {
-						IP6STAT_INC(ip6s_exthdrtoolong);
-						*mp = m;
-						return (-1);
+					if (m->m_len < eoff + rthlen) {
+						m = m_pullup(m, eoff + rthlen);
+						if (m == NULL) {
+							IP6STAT_INC(
+							    ip6s_exthdrtoolong);
+							*mp = m;
+							return (-1);
+						}
 					}
 					rth0 = (struct ip6_rthdr0 *)
 					    (mtod(m, caddr_t) + eoff);
@@ -982,11 +1003,14 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp
 				nxt = rth->ip6r_nxt;
 				break;
 			case IPPROTO_FRAGMENT:
-				m = m_pullup(m, eoff + sizeof(struct ip6_frag));
-				if (m == NULL) {
-					IP6STAT_INC(ip6s_exthdrtoolong);
-					*mp = m;
-					return (-1);
+				if (m->m_len < eoff + sizeof(struct ip6_frag)) {
+					m = m_pullup(m, eoff +
+					    sizeof(struct ip6_frag));
+					if (m == NULL) {
+						IP6STAT_INC(ip6s_exthdrtoolong);
+						*mp = m;
+						return (-1);
+					}
 				}
 				fh = (struct ip6_frag *)(mtod(m, caddr_t) +
 				    eoff);
@@ -1295,11 +1319,14 @@ ni6_input(struct mbuf *m, int off, struct prison *pr)
 			mtx_unlock(&pr->pr_mtx);
 			if (!n || n->m_next || n->m_len == 0)
 				goto bad;
-			m = m_pullup(m, off + sizeof(struct icmp6_nodeinfo) +
-			    subjlen);
-			if (m == NULL) {
-				IP6STAT_INC(ip6s_exthdrtoolong);
-				goto bad;
+			if (m->m_len < off + sizeof(struct icmp6_nodeinfo) +
+			    subjlen) {
+				m = m_pullup(m, off +
+				    sizeof(struct icmp6_nodeinfo) + subjlen);
+				if (m == NULL) {
+					IP6STAT_INC(ip6s_exthdrtoolong);
+					goto bad;
+				}
 			}
 			/* ip6 possibly invalid but not used after. */
 			ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off);
@@ -2201,10 +2228,12 @@ icmp6_redirect_input(struct mbuf *m, int off)
 
 	ip6 = mtod(m, struct ip6_hdr *);
 	icmp6len = ntohs(ip6->ip6_plen);
-	m = m_pullup(m, off + icmp6len);
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		return;
+	if (m->m_len < off + icmp6len) {
+		m = m_pullup(m, off + icmp6len);
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			return;
+		}
 	}
 	ip6 = mtod(m, struct ip6_hdr *);
 	nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);

Modified: head/sys/netinet6/ip6_input.c
==============================================================================
--- head/sys/netinet6/ip6_input.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet6/ip6_input.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -969,20 +969,24 @@ ip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalert
 	struct ip6_hbh *hbh;
 
 	/* validation of the length of the header */
-	m = m_pullup(m, off + sizeof(*hbh));
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		*mp = NULL;
-		return (-1);
+	if (m->m_len < off + sizeof(*hbh)) {
+		m = m_pullup(m, off + sizeof(*hbh));
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			*mp = NULL;
+			return (-1);
+		}
 	}
 	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
 	hbhlen = (hbh->ip6h_len + 1) << 3;
 
-	m = m_pullup(m, off + hbhlen);
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		*mp = NULL;
-		return (-1);
+	if (m->m_len < off + hbhlen) {
+		m = m_pullup(m, off + hbhlen);
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			*mp = NULL;
+			return (-1);
+		}
 	}
 	hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
 	off += hbhlen;

Modified: head/sys/netinet6/ip6_mroute.c
==============================================================================
--- head/sys/netinet6/ip6_mroute.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet6/ip6_mroute.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -1745,10 +1745,12 @@ pim6_input(struct mbuf *m, int off, int proto, void *a
 	 * Make sure that the IP6 and PIM headers in contiguous memory, and
 	 * possibly the PIM REGISTER header
 	 */
-	m = m_pullup(m, off + minlen);
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		return (IPPROTO_DONE);
+	if (m->m_len < off + minlen) {
+		m = m_pullup(m, off + minlen);
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			return (IPPROTO_DONE);
+		}
 	}
 	ip6 = mtod(m, struct ip6_hdr *);
 	pim = (struct pim *)((caddr_t)ip6 + off);

Modified: head/sys/netinet6/mld6.c
==============================================================================
--- head/sys/netinet6/mld6.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet6/mld6.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -1263,10 +1263,12 @@ mld_input(struct mbuf **mp, int off, int icmp6len)
 	ifp = m->m_pkthdr.rcvif;
 
 	/* Pullup to appropriate size. */
-	m = m_pullup(m, off + sizeof(*mld));
-	if (m == NULL) {
-		ICMP6STAT_INC(icp6s_badlen);
-		return (IPPROTO_DONE);
+	if (m->m_len < off + sizeof(*mld)) {
+		m = m_pullup(m, off + sizeof(*mld));
+		if (m == NULL) {
+			ICMP6STAT_INC(icp6s_badlen);
+			return (IPPROTO_DONE);
+		}
 	}
 	mld = (struct mld_hdr *)(mtod(m, uint8_t *) + off);
 	if (mld->mld_type == MLD_LISTENER_QUERY &&
@@ -1275,10 +1277,12 @@ mld_input(struct mbuf **mp, int off, int icmp6len)
 	} else {
 		mldlen = sizeof(struct mld_hdr);
 	}
-	m = m_pullup(m, off + mldlen);
-	if (m == NULL) {
-		ICMP6STAT_INC(icp6s_badlen);
-		return (IPPROTO_DONE);
+	if (m->m_len < off + mldlen) {
+		m = m_pullup(m, off + mldlen);
+		if (m == NULL) {
+			ICMP6STAT_INC(icp6s_badlen);
+			return (IPPROTO_DONE);
+		}
 	}
 	*mp = m;
 	ip6 = mtod(m, struct ip6_hdr *);

Modified: head/sys/netinet6/nd6_nbr.c
==============================================================================
--- head/sys/netinet6/nd6_nbr.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet6/nd6_nbr.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -148,10 +148,12 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
 		goto bads;
 	}
 
-	m = m_pullup(m, off + icmp6len);
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		return;
+	if (m->m_len < off + icmp6len) {
+		m = m_pullup(m, off + icmp6len);
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			return;
+		}
 	}
 	ip6 = mtod(m, struct ip6_hdr *);
 	nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
@@ -652,10 +654,12 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
 		goto bad;
 	}
 
-	m = m_pullup(m, off + icmp6len);
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		return;
+	if (m->m_len < off + icmp6len) {
+		m = m_pullup(m, off + icmp6len);
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			return;
+		}
 	}
 	ip6 = mtod(m, struct ip6_hdr *);
 	nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off);

Modified: head/sys/netinet6/nd6_rtr.c
==============================================================================
--- head/sys/netinet6/nd6_rtr.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet6/nd6_rtr.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -190,10 +190,12 @@ nd6_rs_input(struct mbuf *m, int off, int icmp6len)
 	if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
 		goto freeit;
 
-	m = m_pullup(m, off + icmp6len);
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		return;
+	if (m->m_len < off + icmp6len) {
+		m = m_pullup(m, off + icmp6len);
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			return;
+		}
 	}
 	ip6 = mtod(m, struct ip6_hdr *);
 	nd_rs = (struct nd_router_solicit *)((caddr_t)ip6 + off);
@@ -388,10 +390,12 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
 		goto bad;
 	}
 
-	m = m_pullup(m, off + icmp6len);
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		return;
+	if (m->m_len < off + icmp6len) {
+		m = m_pullup(m, off + icmp6len);
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			return;
+		}
 	}
 	ip6 = mtod(m, struct ip6_hdr *);
 	nd_ra = (struct nd_router_advert *)((caddr_t)ip6 + off);

Modified: head/sys/netinet6/route6.c
==============================================================================
--- head/sys/netinet6/route6.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet6/route6.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -83,11 +83,13 @@ route6_input(struct mbuf **mp, int *offp, int proto)
 	}
 #endif
 
-	m = m_pullup(m, off + sizeof(*rh));
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		*mp = NULL;
-		return (IPPROTO_DONE);
+	if (m->m_len < off + sizeof(*rh)) {
+		m = m_pullup(m, off + sizeof(*rh));
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			*mp = NULL;
+			return (IPPROTO_DONE);
+		}
 	}
 	ip6 = mtod(m, struct ip6_hdr *);
 	rh = (struct ip6_rthdr *)((caddr_t)ip6 + off);

Modified: head/sys/netinet6/sctp6_usrreq.c
==============================================================================
--- head/sys/netinet6/sctp6_usrreq.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet6/sctp6_usrreq.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -103,10 +103,12 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, 
 	SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
 	/* Get IP, SCTP, and first chunk header together in the first mbuf. */
 	offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
-	m = m_pullup(m, offset);
-	if (m == NULL) {
-		SCTP_STAT_INCR(sctps_hdrops);
-		return (IPPROTO_DONE);
+	if (m->m_len < offset) {
+		m = m_pullup(m, offset);
+		if (m == NULL) {
+			SCTP_STAT_INCR(sctps_hdrops);
+			return (IPPROTO_DONE);
+		}
 	}
 	ip6 = mtod(m, struct ip6_hdr *);
 	sh = (struct sctphdr *)(mtod(m, caddr_t) + iphlen);

Modified: head/sys/netinet6/udp6_usrreq.c
==============================================================================
--- head/sys/netinet6/udp6_usrreq.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netinet6/udp6_usrreq.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -223,11 +223,13 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 
 	ifp = m->m_pkthdr.rcvif;
 
-	m = m_pullup(m, off + sizeof(struct udphdr));
-	if (m == NULL) {
-		IP6STAT_INC(ip6s_exthdrtoolong);
-		*mp = NULL;
-		return (IPPROTO_DONE);
+	if (m->m_len < off + sizeof(struct udphdr)) {
+		m = m_pullup(m, off + sizeof(struct udphdr));
+		if (m == NULL) {
+			IP6STAT_INC(ip6s_exthdrtoolong);
+			*mp = NULL;
+			return (IPPROTO_DONE);
+		}
 	}
 	ip6 = mtod(m, struct ip6_hdr *);
 	uh = (struct udphdr *)((caddr_t)ip6 + off);

Modified: head/sys/netipsec/xform_ah.c
==============================================================================
--- head/sys/netipsec/xform_ah.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netipsec/xform_ah.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -575,12 +575,14 @@ ah_input(struct mbuf *m, struct secasvar *sav, int ski
 	/* Figure out header size. */
 	rplen = HDRSIZE(sav);
 
-	m = m_pullup(m, skip + rplen);
-	if (m == NULL) {
-		DPRINTF(("ah_input: cannot pullup header\n"));
-		AHSTAT_INC(ahs_hdrops);		/*XXX*/
-		error = ENOBUFS;
-		goto bad;
+	if (m->m_len < skip + rplen) {
+		m = m_pullup(m, skip + rplen);
+		if (m == NULL) {
+			DPRINTF(("ah_input: cannot pullup header\n"));
+			AHSTAT_INC(ahs_hdrops);		/*XXX*/
+			error = ENOBUFS;
+			goto bad;
+		}
 	}
 	ah = (struct newah *)(mtod(m, caddr_t) + skip);
 

Modified: head/sys/netipsec/xform_esp.c
==============================================================================
--- head/sys/netipsec/xform_esp.c	Sat Nov 30 21:11:17 2019	(r355253)
+++ head/sys/netipsec/xform_esp.c	Sun Dec  1 00:22:04 2019	(r355254)
@@ -308,12 +308,14 @@ esp_input(struct mbuf *m, struct secasvar *sav, int sk
 		goto bad;
 	}
 
-	m = m_pullup(m, skip + sizeof(*esp));
-	if (m == NULL) {
-		DPRINTF(("%s: cannot pullup header\n", __func__));
-		ESPSTAT_INC(esps_hdrops);	/*XXX*/
-		error = ENOBUFS;
-		goto bad;
+	if (m->m_len < skip + sizeof(*esp)) {
+		m = m_pullup(m, skip + sizeof(*esp));
+		if (m == NULL) {
+			DPRINTF(("%s: cannot pullup header\n", __func__));
+			ESPSTAT_INC(esps_hdrops);	/*XXX*/
+			error = ENOBUFS;
+			goto bad;
+		}
 	}
 	esp = (struct newesp *)(mtod(m, caddr_t) + skip);
 


More information about the svn-src-all mailing list