Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 29 May 2018 00:53:54 +0000 (UTC)
From:      Matt Macy <mmacy@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r334305 - head/sys/net
Message-ID:  <201805290053.w4T0rspX052002@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mmacy
Date: Tue May 29 00:53:53 2018
New Revision: 334305
URL: https://svnweb.freebsd.org/changeset/base/334305

Log:
  route: fix missed ref adds
   - ensure that we bump the ifa ref whenever we add a reference
   - defer freeing epoch protected references until after the if_purgaddrs
     loop

Modified:
  head/sys/net/if.c
  head/sys/net/route.c

Modified: head/sys/net/if.c
==============================================================================
--- head/sys/net/if.c	Tue May 29 00:19:23 2018	(r334304)
+++ head/sys/net/if.c	Tue May 29 00:53:53 2018	(r334305)
@@ -967,7 +967,7 @@ if_purgeaddrs(struct ifnet *ifp)
 {
 	struct ifaddr *ifa, *next;
 
-	/* XXX cannot hold IF_ADDR_WLOCK over called functions. */
+	NET_EPOCH_ENTER();
 	CK_STAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
 		if (ifa->ifa_addr->sa_family == AF_LINK)
 			continue;
@@ -997,6 +997,7 @@ if_purgeaddrs(struct ifnet *ifp)
 		IF_ADDR_WUNLOCK(ifp);
 		ifa_free(ifa);
 	}
+	NET_EPOCH_EXIT();
 }
 
 /*
@@ -2196,6 +2197,10 @@ link_rtrequest(int cmd, struct rtentry *rt, struct rt_
 	ifa = ifaof_ifpforaddr(dst, ifp);
 	if (ifa) {
 		oifa = rt->rt_ifa;
+		if (oifa != ifa) {
+			ifa_free(oifa);
+			ifa_ref(ifa);
+		}
 		rt->rt_ifa = ifa;
 		if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
 			ifa->ifa_rtrequest(cmd, rt, info);
@@ -3675,10 +3680,8 @@ if_delmulti_ifma_flags(struct ifmultiaddr *ifma, int f
 		CK_STAILQ_FOREACH(oifp, &V_ifnet, if_link)
 			if (ifp == oifp)
 				break;
-		if (ifp != oifp) {
-			printf("%s: ifnet %p disappeared\n", __func__, ifp);
+		if (ifp != oifp)
 			ifp = NULL;
-		}
 		IFNET_RUNLOCK_NOSLEEP();
 	}
 #endif

Modified: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c	Tue May 29 00:19:23 2018	(r334304)
+++ head/sys/net/route.c	Tue May 29 00:53:53 2018	(r334305)
@@ -653,6 +653,7 @@ rtredirect_fib(struct sockaddr *dst,
 			info.rti_info[RTAX_DST] = dst;
 			info.rti_info[RTAX_GATEWAY] = gateway;
 			info.rti_info[RTAX_NETMASK] = netmask;
+			ifa_ref(ifa);
 			info.rti_ifa = ifa;
 			info.rti_flags = flags;
 			error = rtrequest1_fib(RTM_ADD, &info, &rt, fibnum);
@@ -899,7 +900,7 @@ rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *
 	info->rti_flags = rt->rt_flags;
 	info->rti_ifp = rt->rt_ifp;
 	info->rti_ifa = rt->rt_ifa;
-
+	ifa_ref(info->rti_ifa);
 	if (flags & NHR_REF) {
 		/* Do 'traditional' refcouting */
 		if_ref(info->rti_ifp);
@@ -1275,12 +1276,14 @@ int
 rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum)
 {
 	struct ifaddr *ifa;
-	int error = 0;
+	int needref, error;
 
 	/*
 	 * ifp may be specified by sockaddr_dl
 	 * when protocol address is ambiguous.
 	 */
+	error = 0;
+	needref = (info->rti_ifa == NULL);
 	NET_EPOCH_ENTER();
 	if (info->rti_ifp == NULL && ifpaddr != NULL &&
 	    ifpaddr->sa_family == AF_LINK &&
@@ -1303,7 +1306,7 @@ rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum)
 			info->rti_ifa = ifa_ifwithroute(flags, sa, sa,
 							fibnum);
 	}
-	if ((ifa = info->rti_ifa) != NULL) {
+	if (needref && info->rti_ifa != NULL) {
 		if (info->rti_ifp == NULL)
 			info->rti_ifp = ifa->ifa_ifp;
 		ifa_ref(info->rti_ifa);
@@ -1785,6 +1788,7 @@ rtrequest1_fib_change(struct rib_head *rnh, struct rt_
 		if (rt->rt_ifa->ifa_rtrequest != NULL)
 			rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, info);
 		ifa_free(rt->rt_ifa);
+		rt->rt_ifa = NULL;
 	}
 	/* Update gateway address */
 	if (info->rti_info[RTAX_GATEWAY] != NULL) {
@@ -1836,8 +1840,10 @@ rtrequest1_fib_change(struct rib_head *rnh, struct rt_
 	}
 bad:
 	RT_UNLOCK(rt);
-	if (free_ifa != 0)
+	if (free_ifa != 0) {
 		ifa_free(info->rti_ifa);
+		info->rti_ifa = NULL;
+	}
 	return (error);
 }
 
@@ -2052,6 +2058,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fi
 		 * Do the actual request
 		 */
 		bzero((caddr_t)&info, sizeof(info));
+		ifa_ref(ifa);
 		info.rti_ifa = ifa;
 		info.rti_flags = flags |
 		    (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;



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