svn commit: r339682 - head/sys/netinet6

Bjoern A. Zeeb bz at FreeBSD.org
Wed Oct 24 13:11:11 UTC 2018


Author: bz
Date: Wed Oct 24 10:42:35 2018
New Revision: 339682
URL: https://svnweb.freebsd.org/changeset/base/339682

Log:
  rip6_input() inp validation after epoch(9)
  
  After r335924 rip6_input() needs inp validation to avoid
  working on FREED inps.
  
  Apply the relevant bits from r335497,r335501 (rip_input() change)
  to the IPv6 counterpart.
  
  PR:			232194
  Reviewed by:		rgrimes, ae (,hps)
  MFC after:		3 days
  Differential Revision:	https://reviews.freebsd.org/D17594

Modified:
  head/sys/netinet6/raw_ip6.c

Modified: head/sys/netinet6/raw_ip6.c
==============================================================================
--- head/sys/netinet6/raw_ip6.c	Wed Oct 24 08:45:33 2018	(r339681)
+++ head/sys/netinet6/raw_ip6.c	Wed Oct 24 10:42:35 2018	(r339682)
@@ -187,6 +187,45 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
 		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
 		    !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
 			continue;
+		if (last != NULL) {
+			struct mbuf *n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
+
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+			/*
+			 * Check AH/ESP integrity.
+			 */
+			if (IPSEC_ENABLED(ipv6)) {
+				if (n != NULL &&
+				    IPSEC_CHECK_POLICY(ipv6, n, last) != 0) {
+					m_freem(n);
+					/* Do not inject data into pcb. */
+					n = NULL;
+				}
+			}
+#endif /* IPSEC */
+			if (n) {
+				if (last->inp_flags & INP_CONTROLOPTS ||
+				    last->inp_socket->so_options & SO_TIMESTAMP)
+					ip6_savecontrol(last, n, &opts);
+				/* strip intermediate headers */
+				m_adj(n, *offp);
+				if (sbappendaddr(&last->inp_socket->so_rcv,
+						(struct sockaddr *)&fromsa,
+						 n, opts) == 0) {
+					m_freem(n);
+					if (opts)
+						m_freem(opts);
+					RIP6STAT_INC(rip6s_fullsock);
+				} else
+					sorwakeup(last->inp_socket);
+				opts = NULL;
+			}
+			INP_RUNLOCK(last);
+			last = NULL;
+		}
+		INP_RLOCK(in6p);
+		if (__predict_false(in6p->inp_flags2 & INP_FREED))
+			goto skip_2;
 		if (jailed_without_vnet(in6p->inp_cred)) {
 			/*
 			 * Allow raw socket in jail to receive multicast;
@@ -196,16 +235,14 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
 			if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
 			    prison_check_ip6(in6p->inp_cred,
 			    &ip6->ip6_dst) != 0)
-				continue;
+				goto skip_2;
 		}
-		INP_RLOCK(in6p);
 		if (in6p->in6p_cksum != -1) {
 			RIP6STAT_INC(rip6s_isum);
 			if (in6_cksum(m, proto, *offp,
 			    m->m_pkthdr.len - *offp)) {
-				INP_RUNLOCK(in6p);
 				RIP6STAT_INC(rip6s_badsum);
-				continue;
+				goto skip_2;
 			}
 		}
 		/*
@@ -251,46 +288,13 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
 			}
 			if (blocked != MCAST_PASS) {
 				IP6STAT_INC(ip6s_notmember);
-				INP_RUNLOCK(in6p);
-				continue;
+				goto skip_2;
 			}
 		}
-		if (last != NULL) {
-			struct mbuf *n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
-
-#if defined(IPSEC) || defined(IPSEC_SUPPORT)
-			/*
-			 * Check AH/ESP integrity.
-			 */
-			if (IPSEC_ENABLED(ipv6)) {
-				if (n != NULL &&
-				    IPSEC_CHECK_POLICY(ipv6, n, last) != 0) {
-					m_freem(n);
-					/* Do not inject data into pcb. */
-					n = NULL;
-				}
-			}
-#endif /* IPSEC */
-			if (n) {
-				if (last->inp_flags & INP_CONTROLOPTS ||
-				    last->inp_socket->so_options & SO_TIMESTAMP)
-					ip6_savecontrol(last, n, &opts);
-				/* strip intermediate headers */
-				m_adj(n, *offp);
-				if (sbappendaddr(&last->inp_socket->so_rcv,
-						(struct sockaddr *)&fromsa,
-						 n, opts) == 0) {
-					m_freem(n);
-					if (opts)
-						m_freem(opts);
-					RIP6STAT_INC(rip6s_fullsock);
-				} else
-					sorwakeup(last->inp_socket);
-				opts = NULL;
-			}
-			INP_RUNLOCK(last);
-		}
 		last = in6p;
+		continue;
+skip_2:
+		INP_RUNLOCK(in6p);
 	}
 	INP_INFO_RUNLOCK_ET(&V_ripcbinfo, et);
 #if defined(IPSEC) || defined(IPSEC_SUPPORT)


More information about the svn-src-all mailing list