diff options
author | rwatson <rwatson@FreeBSD.org> | 2009-06-23 20:19:09 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2009-06-23 20:19:09 +0000 |
commit | c9ef486fe1d7da6a2212a337eacc5ed5b40f85d9 (patch) | |
tree | 5ce1a7dad67026f119a839b3325454ebafa72c51 /sys/netinet6/icmp6.c | |
parent | f75c2385c686d82292982283b5f0a9c9988beda8 (diff) | |
download | FreeBSD-src-c9ef486fe1d7da6a2212a337eacc5ed5b40f85d9.zip FreeBSD-src-c9ef486fe1d7da6a2212a337eacc5ed5b40f85d9.tar.gz |
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)
Diffstat (limited to 'sys/netinet6/icmp6.c')
-rw-r--r-- | sys/netinet6/icmp6.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 11e6cd6..786ddc2 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -1244,11 +1244,13 @@ ni6_input(struct mbuf *m, int off) if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) && !(V_icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK)) { + ifa_free(&ia6->ia_ifa); nd6log((LOG_DEBUG, "ni6_input: ignore node info to " "a temporary address in %s:%d", __FILE__, __LINE__)); goto bad; } + ifa_free(&ia6->ia_ifa); } /* validate query Subject field. */ @@ -2074,7 +2076,7 @@ icmp6_reflect(struct mbuf *m, size_t off) INIT_VNET_INET6(curvnet); struct ip6_hdr *ip6; struct icmp6_hdr *icmp6; - struct in6_ifaddr *ia; + struct in6_ifaddr *ia = NULL; int plen; int type, code; struct ifnet *outif = NULL; @@ -2220,9 +2222,13 @@ icmp6_reflect(struct mbuf *m, size_t off) if (outif) icmp6_ifoutstat_inc(outif, type, code); + if (ia != NULL) + ifa_free(&ia->ia_ifa); return; bad: + if (ia != NULL) + ifa_free(&ia->ia_ifa); m_freem(m); return; } @@ -2541,6 +2547,8 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt) IN6_IFF_ANYCAST)) == NULL) goto fail; ifp_ll6 = &ia->ia_addr.sin6_addr; + /* XXXRW: reference released prematurely. */ + ifa_free(&ia->ia_ifa); } /* get ip6 linklocal address for the router. */ |