diff options
author | Robert Watson <rwatson@FreeBSD.org> | 2009-06-23 20:19:09 +0000 |
---|---|---|
committer | Robert Watson <rwatson@FreeBSD.org> | 2009-06-23 20:19:09 +0000 |
commit | 8c0fec805f76bef04e007ca08552bd80ab64daf9 (patch) | |
tree | 5ce1a7dad67026f119a839b3325454ebafa72c51 /sys/netinet6/raw_ip6.c | |
parent | abcd328be6335621a1152ed2ce08b4550ab4242c (diff) | |
download | src-8c0fec805f76bef04e007ca08552bd80ab64daf9.tar.gz src-8c0fec805f76bef04e007ca08552bd80ab64daf9.zip |
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)
Notes
Notes:
svn path=/head/; revision=194760
Diffstat (limited to 'sys/netinet6/raw_ip6.c')
-rw-r--r-- | sys/netinet6/raw_ip6.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 3c514d888259..cd7d8173de4f 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -714,7 +714,7 @@ rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) INIT_VNET_INET6(so->so_vnet); struct inpcb *inp; struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; - struct ifaddr *ia = NULL; + struct ifaddr *ifa = NULL; int error = 0; inp = sotoinpcb(so); @@ -730,14 +730,17 @@ rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) return (error); if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) && - (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0) + (ifa = ifa_ifwithaddr((struct sockaddr *)addr)) == NULL) return (EADDRNOTAVAIL); - if (ia && - ((struct in6_ifaddr *)ia)->ia6_flags & + if (ifa != NULL && + ((struct in6_ifaddr *)ifa)->ia6_flags & (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY| IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { + ifa_free(ifa); return (EADDRNOTAVAIL); } + if (ifa != NULL) + ifa_free(ifa); INP_INFO_WLOCK(&V_ripcbinfo); INP_WLOCK(inp); inp->in6p_laddr = addr->sin6_addr; |