From c9ef486fe1d7da6a2212a337eacc5ed5b40f85d9 Mon Sep 17 00:00:00 2001 From: rwatson Date: Tue, 23 Jun 2009 20:19:09 +0000 Subject: Modify most routines returning 'struct ifaddr *' to return references rather than pointers, requiring callers to properly dispose of those references. The following routines now return references: ifaddr_byindex ifa_ifwithaddr ifa_ifwithbroadaddr ifa_ifwithdstaddr ifa_ifwithnet ifaof_ifpforaddr ifa_ifwithroute ifa_ifwithroute_fib rt_getifa rt_getifa_fib IFP_TO_IA ip_rtaddr in6_ifawithifp in6ifa_ifpforlinklocal in6ifa_ifpwithaddr in6_ifadd carp_iamatch6 ip6_getdstifaddr Remove unused macro which didn't have required referencing: IFP_TO_IA6 This closes many small races in which changes to interface or address lists while an ifaddr was in use could lead to use of freed memory (etc). In a few cases, add missing if_addr_list locking required to safely acquire references. Because of a lack of deep copying support, we accept a race in which an in6_ifaddr pointed to by mbuf tags and extracted with ip6_getdstifaddr() doesn't hold a reference while in transmit. Once we have mbuf tag deep copy support, this can be fixed. Reviewed by: bz Obtained from: Apple, Inc. (portions) MFC after: 6 weeks (portions) --- sys/netinet6/in6_ifattach.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'sys/netinet6/in6_ifattach.c') diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 1888017..ebfdf6e 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -253,6 +253,7 @@ in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6) return -1; found: + IF_ADDR_LOCK_ASSERT(ifp); addr = LLADDR(sdl); addrlen = sdl->sdl_alen; @@ -513,6 +514,7 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) /* NOTREACHED */ } #endif + ifa_free(&ia->ia_ifa); /* * Make the link-local prefix (fe80::%link/64) as on-link. @@ -737,11 +739,15 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) * XXX multiple loopback interface case. */ if ((ifp->if_flags & IFF_LOOPBACK) != 0) { + struct ifaddr *ifa; + in6 = in6addr_loopback; - if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) { + ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &in6); + if (ifa == NULL) { if (in6_ifattach_loopback(ifp) != 0) return; - } + } else + ifa_free(ifa); } /* @@ -755,7 +761,8 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) } else { /* failed to assign linklocal address. bark? */ } - } + } else + ifa_free(&ia->ia_ifa); } #ifdef IFT_STF /* XXX */ -- cgit v1.1