Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144995382
D17599.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D17599.diff
View Options
Index: sys/net/if.c
===================================================================
--- sys/net/if.c
+++ sys/net/if.c
@@ -425,12 +425,12 @@
ifaddr_byindex(u_short idx)
{
struct ifnet *ifp;
- struct ifaddr *ifa = NULL;
+ struct ifaddr *ifa;
IFNET_RLOCK_NOSLEEP();
ifp = ifnet_byindex_locked(idx);
- if (ifp != NULL && (ifa = ifp->if_addr) != NULL)
- ifa_ref(ifa);
+ if (ifp == NULL || (ifa = ifp->if_addr) == NULL || ifa_ref(ifa) == 0)
+ ifa = NULL; /* failure */
IFNET_RUNLOCK_NOSLEEP();
return (ifa);
}
@@ -969,7 +969,7 @@
while (1) {
NET_EPOCH_ENTER();
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- if (ifa->ifa_addr->sa_family != AF_LINK)
+ if (ifa->ifa_addr->sa_family != AF_LINK && ifa_ref(ifa) != 0)
break;
}
NET_EPOCH_EXIT();
@@ -987,20 +987,22 @@
ifr.ifra_broadaddr = *ifa->ifa_dstaddr;
if (in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
NULL) == 0)
- continue;
+ goto skip;
}
#endif /* INET */
#ifdef INET6
if (ifa->ifa_addr->sa_family == AF_INET6) {
in6_purgeaddr(ifa);
/* ifp_addrhead is already updated */
- continue;
+ goto skip;
}
#endif /* INET6 */
IF_ADDR_WLOCK(ifp);
CK_STAILQ_REMOVE(&ifp->if_addrhead, ifa, ifaddr, ifa_link);
IF_ADDR_WUNLOCK(ifp);
ifa_free(ifa);
+skip:
+ ifa_free(ifa);
}
}
@@ -1834,11 +1836,11 @@
return (NULL);
}
-void
+int
ifa_ref(struct ifaddr *ifa)
{
- refcount_acquire(&ifa->ifa_refcnt);
+ return (refcount_acquire_if_not_zero(&ifa->ifa_refcnt));
}
static void
@@ -2205,12 +2207,9 @@
return;
NET_EPOCH_ENTER();
ifa = ifaof_ifpforaddr(dst, ifp);
- if (ifa) {
+ if (ifa != NULL && ifa_ref(ifa) != 0) {
oifa = rt->rt_ifa;
- if (oifa != ifa) {
- ifa_free(oifa);
- ifa_ref(ifa);
- }
+ ifa_free(oifa);
rt->rt_ifa = ifa;
if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
ifa->ifa_rtrequest(cmd, rt, info);
Index: sys/net/if_spppsubr.c
===================================================================
--- sys/net/if_spppsubr.c
+++ sys/net/if_spppsubr.c
@@ -4882,10 +4882,8 @@
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family == AF_INET) {
si = (struct sockaddr_in *)ifa->ifa_addr;
- if (si != NULL) {
- ifa_ref(ifa);
+ if (si != NULL && ifa_ref(ifa) != 0)
break;
- }
}
}
if_addr_runlock(ifp);
@@ -4999,8 +4997,9 @@
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family == AF_INET6) {
sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
- if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
- ifa_ref(ifa);
+ if (sin6 != NULL &&
+ IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
+ ifa_ref(ifa) != 0) {
break;
}
}
Index: sys/net/if_var.h
===================================================================
--- sys/net/if_var.h
+++ sys/net/if_var.h
@@ -548,7 +548,7 @@
struct ifaddr * ifa_alloc(size_t size, int flags);
void ifa_free(struct ifaddr *ifa);
-void ifa_ref(struct ifaddr *ifa);
+int ifa_ref(struct ifaddr *ifa) __result_use_check;
/*
* Multicast address structure. This is analogous to the ifaddr
Index: sys/net/route.c
===================================================================
--- sys/net/route.c
+++ sys/net/route.c
@@ -652,19 +652,22 @@
RTFREE_LOCKED(rt);
flags |= RTF_DYNAMIC;
- bzero((caddr_t)&info, sizeof(info));
- 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);
- if (rt != NULL) {
- RT_LOCK(rt);
- flags = rt->rt_flags;
+
+ if (ifa_ref(ifa) != 0) {
+ bzero((caddr_t)&info, sizeof(info));
+ info.rti_info[RTAX_DST] = dst;
+ info.rti_info[RTAX_GATEWAY] = gateway;
+ info.rti_info[RTAX_NETMASK] = netmask;
+ info.rti_ifa = ifa;
+ info.rti_flags = flags;
+ error = rtrequest1_fib(RTM_ADD, &info, &rt, fibnum);
+ if (rt != NULL) {
+ RT_LOCK(rt);
+ flags = rt->rt_flags;
+ }
+ } else {
+ error = ENXIO;
}
-
stat = &V_rtstat.rts_dynamic;
} else {
@@ -903,7 +906,8 @@
info->rti_flags = rt->rt_flags;
info->rti_ifp = rt->rt_ifp;
info->rti_ifa = rt->rt_ifa;
- ifa_ref(info->rti_ifa);
+ if (ifa_ref(info->rti_ifa) == 0)
+ return (ENXIO);
if (flags & NHR_REF) {
/* Do 'traditional' refcouting */
if_ref(info->rti_ifp);
@@ -1313,7 +1317,8 @@
if (needref && info->rti_ifa != NULL) {
if (info->rti_ifp == NULL)
info->rti_ifp = info->rti_ifa->ifa_ifp;
- ifa_ref(info->rti_ifa);
+ if (ifa_ref(info->rti_ifa) == 0)
+ error = ENXIO;
} else
error = ENETUNREACH;
NET_EPOCH_EXIT();
@@ -1627,7 +1632,11 @@
* examine the ifa and ifa->ifa_ifp if it so desires.
*/
ifa = info->rti_ifa;
- ifa_ref(ifa);
+ if (ifa_ref(ifa) == 0) {
+ R_Free(rt_key(rt));
+ uma_zfree(V_rtzone, rt);
+ return (ENXIO);
+ }
rt->rt_ifa = ifa;
rt->rt_ifp = ifa->ifa_ifp;
rt->rt_weight = 1;
@@ -1805,7 +1814,11 @@
}
if (info->rti_ifa != NULL && info->rti_ifa != rt->rt_ifa) {
- ifa_ref(info->rti_ifa);
+ if (ifa_ref(info->rti_ifa) == 0) {
+ error = ENXIO;
+ free_ifa = 0;
+ goto bad;
+ }
rt->rt_ifa = info->rti_ifa;
rt->rt_ifp = info->rti_ifp;
}
@@ -1970,6 +1983,8 @@
}
if (dst->sa_len == 0)
return(EINVAL);
+ if (ifa_ref(ifa) == 0)
+ return (ENXIO);
switch (dst->sa_family) {
case AF_INET6:
case AF_INET:
@@ -2063,7 +2078,8 @@
* Do the actual request
*/
bzero((caddr_t)&info, sizeof(info));
- ifa_ref(ifa);
+ if (ifa_ref(ifa) == 0)
+ panic("Cannot get reference on ifa\n");
info.rti_ifa = ifa;
info.rti_flags = flags |
(ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;
@@ -2095,7 +2111,8 @@
if (memcmp(rt->rt_ifa->ifa_addr,
ifa->ifa_addr, ifa->ifa_addr->sa_len)) {
ifa_free(rt->rt_ifa);
- ifa_ref(ifa);
+ if (ifa_ref(ifa) == 0)
+ panic("Cannot get reference on ifa\n");
rt->rt_ifp = ifa->ifa_ifp;
rt->rt_ifa = ifa;
}
@@ -2150,6 +2167,7 @@
error = a_failure;
}
}
+ ifa_free(ifa);
return (error);
}
Index: sys/netinet/if_ether.c
===================================================================
--- sys/netinet/if_ether.c
+++ sys/netinet/if_ether.c
@@ -843,8 +843,8 @@
ia->ia_ifp == ifp) &&
itaddr.s_addr == ia->ia_addr.sin_addr.s_addr &&
(ia->ia_ifa.ifa_carp == NULL ||
- (*carp_iamatch_p)(&ia->ia_ifa, &enaddr))) {
- ifa_ref(&ia->ia_ifa);
+ (*carp_iamatch_p)(&ia->ia_ifa, &enaddr)) &&
+ ifa_ref(&ia->ia_ifa) != 0) {
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto match;
}
@@ -852,8 +852,8 @@
LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash)
if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) ||
ia->ia_ifp == ifp) &&
- isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
- ifa_ref(&ia->ia_ifa);
+ isaddr.s_addr == ia->ia_addr.sin_addr.s_addr &&
+ ifa_ref(&ia->ia_ifa) != 0) {
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto match;
}
@@ -870,8 +870,8 @@
*/
if (is_bridge) {
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) {
- if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) {
- ifa_ref(&ia->ia_ifa);
+ if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia) &&
+ ifa_ref(&ia->ia_ifa) != 0) {
ifp = ia->ia_ifp;
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto match;
@@ -889,9 +889,9 @@
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (ifa->ifa_addr->sa_family == AF_INET &&
(ifa->ifa_carp == NULL ||
- (*carp_iamatch_p)(ifa, &enaddr))) {
+ (*carp_iamatch_p)(ifa, &enaddr)) &&
+ ifa_ref(ifa) != 0) {
ia = ifatoia(ifa);
- ifa_ref(ifa);
IF_ADDR_RUNLOCK(ifp);
goto match;
}
@@ -901,11 +901,11 @@
* If bridging, fall back to using any inet address.
*/
IN_IFADDR_RLOCK(&in_ifa_tracker);
- if (!bridged || (ia = CK_STAILQ_FIRST(&V_in_ifaddrhead)) == NULL) {
+ if (!bridged || (ia = CK_STAILQ_FIRST(&V_in_ifaddrhead)) == NULL ||
+ ifa_ref(&ia->ia_ifa) == 0) {
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto drop;
}
- ifa_ref(&ia->ia_ifa);
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
match:
if (!enaddr)
@@ -1399,9 +1399,10 @@
IF_ADDR_WLOCK(ia->ia_ifa.ifa_ifp);
ia->ia_garp_count = 0;
- if (callout_reset(&ia->ia_garp_timer, (1 << ia->ia_garp_count) * hz,
- garp_rexmit, ia) == 0) {
- ifa_ref(ifa);
+ if (ifa_ref(ifa) != 0 &&
+ callout_reset(&ia->ia_garp_timer, (1 << ia->ia_garp_count) * hz,
+ garp_rexmit, ia) != 0) {
+ ifa_free(ifa);
}
IF_ADDR_WUNLOCK(ia->ia_ifa.ifa_ifp);
}
Index: sys/netinet/in.c
===================================================================
--- sys/netinet/in.c
+++ sys/netinet/in.c
@@ -170,8 +170,8 @@
IN_IFADDR_RLOCK(&in_ifa_tracker);
LIST_FOREACH(it, INADDR_HASH(in), ia_hash) {
- if (it != ia && IA_SIN(it)->sin_addr.s_addr == in) {
- ifa_ref(&it->ia_ifa);
+ if (it != ia && IA_SIN(it)->sin_addr.s_addr == in &&
+ ifa_ref(&it->ia_ifa) != 0) {
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (it);
}
@@ -458,11 +458,12 @@
CK_STAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
IF_ADDR_WUNLOCK(ifp);
- ifa_ref(ifa); /* in_ifaddrhead */
- IN_IFADDR_WLOCK();
- CK_STAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
- LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
- IN_IFADDR_WUNLOCK();
+ if (ifa_ref(ifa) != 0) {
+ IN_IFADDR_WLOCK();
+ CK_STAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
+ LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
+ IN_IFADDR_WUNLOCK();
+ }
/*
* Give the interface a chance to initialize
@@ -865,8 +866,8 @@
* the route itself to it. Make sure that routing daemons
* get a heads-up.
*/
- if ((ia->ia_flags & IFA_ROUTE) == 0) {
- ifa_ref(&ia->ia_ifa);
+ if ((ia->ia_flags & IFA_ROUTE) == 0 &&
+ ifa_ref(&ia->ia_ifa) != 0) {
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
error = rtinit(&(target->ia_ifa), (int)RTM_DELETE,
rtinitflags(target));
Index: sys/netinet/ip_carp.c
===================================================================
--- sys/netinet/ip_carp.c
+++ sys/netinet/ip_carp.c
@@ -669,8 +669,8 @@
error = ELOOP;
}
ifa = error ? NULL : match;
- if (ifa != NULL)
- ifa_ref(ifa);
+ if (ifa != NULL && ifa_ref(ifa) == 0)
+ ifa = NULL;
IF_ADDR_RUNLOCK(ifp);
if (ifa == NULL) {
@@ -891,8 +891,8 @@
best = ifa;
}
IF_ADDR_RUNLOCK(ifp);
- if (best != NULL)
- ifa_ref(best);
+ if (best != NULL && ifa_ref(best) == 0)
+ best = NULL;
return (best);
}
@@ -1176,10 +1176,10 @@
continue;
if (!IN6_ARE_ADDR_EQUAL(taddr, IFA_IN6(ifa)))
continue;
- if (ifa->ifa_carp && ifa->ifa_carp->sc_state != MASTER)
+ if ((ifa->ifa_carp && ifa->ifa_carp->sc_state != MASTER) ||
+ ifa_ref(ifa) == 0) {
ifa = NULL;
- else
- ifa_ref(ifa);
+ }
break;
}
IF_ADDR_RUNLOCK(ifp);
@@ -1890,6 +1890,9 @@
KASSERT(ifa->ifa_carp == NULL, ("%s: ifa %p attached", __func__, ifa));
+ if (ifa_ref(ifa) == 0)
+ return (ENXIO);
+
switch (ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET:
@@ -1899,28 +1902,28 @@
#endif
break;
default:
- return (EPROTOTYPE);
+ error = EPROTOTYPE;
+ goto err;
}
sx_xlock(&carp_sx);
if (ifp->if_carp == NULL) {
- sx_xunlock(&carp_sx);
- return (ENOPROTOOPT);
+ error = ENOPROTOOPT;
+ goto err_unlock;
}
IFNET_FOREACH_CARP(ifp, sc)
if (sc->sc_vhid == vhid)
break;
if (sc == NULL) {
- sx_xunlock(&carp_sx);
- return (ENOENT);
+ error = ENOENT;
+ goto err_unlock;
}
error = carp_multicast_setup(cif, ifa->ifa_addr->sa_family);
if (error) {
CIF_FREE(cif);
- sx_xunlock(&carp_sx);
- return (error);
+ goto err_unlock;
}
index = sc->sc_naddrs + sc->sc_naddrs6 + 1;
@@ -1942,8 +1945,6 @@
#endif
}
- ifa_ref(ifa);
-
CARP_LOCK(sc);
sc->sc_ifas[index - 1] = ifa;
ifa->ifa_carp = sc;
@@ -1954,6 +1955,12 @@
sx_xunlock(&carp_sx);
return (0);
+
+err_unlock:
+ sx_xunlock(&carp_sx);
+err:
+ ifa_free(ifa);
+ return (error);
}
void
Index: sys/netinet/raw_ip.c
===================================================================
--- sys/netinet/raw_ip.c
+++ sys/netinet/raw_ip.c
@@ -758,8 +758,8 @@
IN_IFADDR_RLOCK(&in_ifa_tracker);
CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (ia->ia_ifa.ifa_addr == sa
- && (ia->ia_flags & IFA_ROUTE)) {
- ifa_ref(&ia->ia_ifa);
+ && (ia->ia_flags & IFA_ROUTE) &&
+ ifa_ref(&ia->ia_ifa) != 0) {
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* in_scrubprefix() kills the interface route.
@@ -786,11 +786,11 @@
if (ia->ia_ifa.ifa_addr == sa)
break;
}
- if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) {
+ if (ia == NULL || (ia->ia_flags & IFA_ROUTE) ||
+ ifa_ref(&ia->ia_ifa) == 0) {
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return;
}
- ifa_ref(&ia->ia_ifa);
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
flags = RTF_UP;
ifp = ia->ia_ifa.ifa_ifp;
Index: sys/netinet6/in6.c
===================================================================
--- sys/netinet6/in6.c
+++ sys/netinet6/in6.c
@@ -1118,17 +1118,17 @@
}
ia->ia_ifp = ifp;
- ifa_ref(&ia->ia_ifa); /* if_addrhead */
- IF_ADDR_WLOCK(ifp);
- CK_STAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
- IF_ADDR_WUNLOCK(ifp);
-
- ifa_ref(&ia->ia_ifa); /* in6_ifaddrhead */
- IN6_IFADDR_WLOCK();
- CK_STAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link);
- CK_LIST_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia, ia6_hash);
- IN6_IFADDR_WUNLOCK();
-
+ if (ifa_ref(&ia->ia_ifa) != 0) {
+ IF_ADDR_WLOCK(ifp);
+ CK_STAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
+ IF_ADDR_WUNLOCK(ifp);
+ }
+ if (ifa_ref(&ia->ia_ifa) != 0) {
+ IN6_IFADDR_WLOCK();
+ CK_STAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link);
+ CK_LIST_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia, ia6_hash);
+ IN6_IFADDR_WUNLOCK();
+ }
return (ia);
}
@@ -1457,11 +1457,11 @@
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
"Invoking IPv6 network device address event may sleep");
- ifa_ref(&ia->ia_ifa);
- EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa,
- IFADDR_EVENT_ADD);
- ifa_free(&ia->ia_ifa);
-
+ if (ifa_ref(&ia->ia_ifa) != 0) {
+ EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa,
+ IFADDR_EVENT_ADD);
+ ifa_free(&ia->ia_ifa);
+ }
return (error);
}
@@ -1480,10 +1480,8 @@
continue;
if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
if ((((struct in6_ifaddr *)ifa)->ia6_flags &
- ignoreflags) != 0)
- continue;
- ifa_ref(ifa);
- break;
+ ignoreflags) == 0 && ifa_ref(ifa) != 0)
+ break;
}
}
IF_ADDR_RUNLOCK(ifp);
@@ -1508,8 +1506,8 @@
if (zoneid != 0 &&
zoneid != ia->ia_addr.sin6_scope_id)
continue;
- ifa_ref(&ia->ia_ifa);
- break;
+ if (ifa_ref(&ia->ia_ifa) != 0)
+ break;
}
}
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
@@ -1529,10 +1527,9 @@
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
- if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa))) {
- ifa_ref(ifa);
+ if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)) &&
+ ifa_ref(ifa) != 0)
break;
- }
}
IF_ADDR_RUNLOCK(ifp);
@@ -1864,8 +1861,7 @@
besta = (struct in6_ifaddr *)ifa;
}
}
- if (besta) {
- ifa_ref(&besta->ia_ifa);
+ if (besta && ifa_ref(&besta->ia_ifa) != 0) {
IF_ADDR_RUNLOCK(ifp);
return (besta);
}
@@ -1884,21 +1880,18 @@
dep[1] = (struct in6_ifaddr *)ifa;
continue;
}
-
- if (ifa != NULL)
- ifa_ref(ifa);
+ if (ifa_ref(ifa) == 0)
+ continue;
IF_ADDR_RUNLOCK(ifp);
return (struct in6_ifaddr *)ifa;
}
/* use the last-resort values, that are, deprecated addresses */
- if (dep[0]) {
- ifa_ref((struct ifaddr *)dep[0]);
+ if (dep[0] && ifa_ref((struct ifaddr *)dep[0]) != 0) {
IF_ADDR_RUNLOCK(ifp);
return dep[0];
}
- if (dep[1]) {
- ifa_ref((struct ifaddr *)dep[1]);
+ if (dep[1] && ifa_ref((struct ifaddr *)dep[1]) != 0) {
IF_ADDR_RUNLOCK(ifp);
return dep[1];
}
Index: sys/netinet6/nd6.c
===================================================================
--- sys/netinet6/nd6.c
+++ sys/netinet6/nd6.c
@@ -1106,8 +1106,9 @@
if (!IFA6_IS_DEPRECATED(it6))
public_ifa6 = it6;
}
- if (public_ifa6 != NULL)
- ifa_ref(&public_ifa6->ia_ifa);
+ if (public_ifa6 != NULL &&
+ ifa_ref(&public_ifa6->ia_ifa) == 0)
+ public_ifa6 = NULL;
IF_ADDR_RUNLOCK(ifp);
if (public_ifa6 != NULL) {
Index: sys/netinet6/nd6_nbr.c
===================================================================
--- sys/netinet6/nd6_nbr.c
+++ sys/netinet6/nd6_nbr.c
@@ -1261,12 +1261,16 @@
return;
}
+ if (ifa_ref(ifa) == 0)
+ return; /* Network address has been freed */
+
dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT | M_ZERO);
if (dp == NULL) {
log(LOG_ERR, "nd6_dad_start: memory allocation failed for "
"%s(%s)\n",
ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
+ ifa_free(ifa);
return;
}
callout_init(&dp->dad_timer_ch, 0);
@@ -1283,7 +1287,6 @@
* (re)initialization.
*/
dp->dad_ifa = ifa;
- ifa_ref(dp->dad_ifa);
dp->dad_count = V_ip6_dad_count;
dp->dad_ns_icount = dp->dad_na_icount = 0;
dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
Index: sys/netinet6/nd6_rtr.c
===================================================================
--- sys/netinet6/nd6_rtr.c
+++ sys/netinet6/nd6_rtr.c
@@ -480,7 +480,8 @@
IF_ADDR_RLOCK(ifp);
ifa = CK_STAILQ_FIRST(&ifp->if_addrhead);
info.rti_info[RTAX_IFP] = ifa->ifa_addr;
- ifa_ref(ifa);
+ if (ifa_ref(ifa) == 0)
+ ifa = NULL;
IF_ADDR_RUNLOCK(ifp);
info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
} else
@@ -1909,8 +1910,8 @@
/* XXX: freebsd does not have ifa_ifwithaf */
IF_ADDR_RLOCK(ifp);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- if (ifa->ifa_addr->sa_family == AF_INET6) {
- ifa_ref(ifa);
+ if (ifa->ifa_addr->sa_family == AF_INET6 &&
+ ifa_ref(ifa) != 0) {
break;
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 15, 8:54 PM (17 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28755567
Default Alt Text
D17599.diff (17 KB)
Attached To
Mode
D17599: Fix for double free when deleting entries from epoch managed lists
Attached
Detach File
Event Timeline
Log In to Comment