svn commit: r354855 - head/sys/netinet6

Bjoern A. Zeeb bz at FreeBSD.org
Tue Nov 19 14:53:14 UTC 2019


Author: bz
Date: Tue Nov 19 14:53:13 2019
New Revision: 354855
URL: https://svnweb.freebsd.org/changeset/base/354855

Log:
  mld: fix epoch assertion
  
  in6ifa_ifpforlinklocal() asserts the net epoch.  The test case from r354832
  revealed code paths where we call into the function without having
  acquired the net epoch first and consequently we hit the assert.
  This happens in certain MLD states during VNET shutdown and most people
  normaly not notice this.
  
  For correctness acquire the net epoch around calls to
  mld_v1_transmit_report() in all cases to avoid the assertion firing.
  
  MFC after:	2 weeks
  Sponsored by:	Netflix

Modified:
  head/sys/netinet6/mld6.c

Modified: head/sys/netinet6/mld6.c
==============================================================================
--- head/sys/netinet6/mld6.c	Tue Nov 19 14:46:28 2019	(r354854)
+++ head/sys/netinet6/mld6.c	Tue Nov 19 14:53:13 2019	(r354855)
@@ -1800,6 +1800,7 @@ mld_v1_transmit_report(struct in6_multi *in6m, const i
 	struct mbuf		*mh, *md;
 	struct mld_hdr		*mld;
 
+	NET_EPOCH_ASSERT();
 	IN6_MULTI_LIST_LOCK_ASSERT();
 	MLD_LOCK_ASSERT();
 	
@@ -1968,6 +1969,7 @@ static int
 mld_initial_join(struct in6_multi *inm, struct mld_ifsoftc *mli,
     const int delay)
 {
+	struct epoch_tracker     et;
 	struct ifnet		*ifp;
 	struct mbufq		*mq;
 	int			 error, retval, syncstates;
@@ -2035,8 +2037,10 @@ mld_initial_join(struct in6_multi *inm, struct mld_ifs
 				V_current_state_timers_running6 = 1;
 			} else {
 				inm->in6m_state = MLD_IDLE_MEMBER;
+				NET_EPOCH_ENTER(et);
 				error = mld_v1_transmit_report(inm,
 				     MLD_LISTENER_REPORT);
+				NET_EPOCH_EXIT(et);
 				if (error == 0) {
 					inm->in6m_timer = odelay;
 					V_current_state_timers_running6 = 1;
@@ -2181,6 +2185,7 @@ mld_handle_state_change(struct in6_multi *inm, struct 
 static void
 mld_final_leave(struct in6_multi *inm, struct mld_ifsoftc *mli)
 {
+	struct epoch_tracker     et;
 	int syncstates;
 #ifdef KTR
 	char ip6tbuf[INET6_ADDRSTRLEN];
@@ -2214,7 +2219,9 @@ mld_final_leave(struct in6_multi *inm, struct mld_ifso
 			panic("%s: MLDv2 state reached, not MLDv2 mode",
 			     __func__);
 #endif
+			NET_EPOCH_ENTER(et);
 			mld_v1_transmit_report(inm, MLD_LISTENER_DONE);
+			NET_EPOCH_EXIT(et);
 			inm->in6m_state = MLD_NOT_MEMBER;
 			V_current_state_timers_running6 = 1;
 		} else if (mli->mli_version == MLD_VERSION_2) {
@@ -3194,6 +3201,7 @@ mld_v2_encap_report(struct ifnet *ifp, struct mbuf *m)
 	/*
 	 * RFC3590: OK to send as :: or tentative during DAD.
 	 */
+	NET_EPOCH_ASSERT();
 	ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
 	if (ia == NULL)
 		CTR1(KTR_MLD, "%s: warning: ia is NULL", __func__);


More information about the svn-src-head mailing list