svn commit: r207013 - in stable/8/sys: net netinet netinet6
Bjoern A. Zeeb
bz at FreeBSD.org
Wed Apr 21 19:51:22 UTC 2010
Author: bz
Date: Wed Apr 21 19:51:22 2010
New Revision: 207013
URL: http://svn.freebsd.org/changeset/base/207013
Log:
MFC r206481:
Plug reference leaks in the link-layer code ("new-arp") that previously
prevented the link-layer entry from being freed.
In both in.c and in6.c (though that code path seems to be basically dead)
plug a reference leak in case of a pending callout being drained.
In if_ether.c consistently add a reference before resetting the callout
and in case we canceled a pending one remove the reference for that.
In the final case in arptimer, before freeing the expired entry, remove
the reference again and explicitly call callout_stop() to clear the active
flag.
In nd6.c:nd6_free() we are only ever called from the callout function and
thus need to remove the reference there as well before calling into
llentry_free().
In if_llatbl.c when freeing the entire tables make sure that in case we
cancel a pending callout to remove the reference as well.
Reviewed by: qingli (earlier version)
MFC after: 10 days
Problem observed, patch tested by: simon on ipv6gw.f.o,
Christian Kratzer (ck cksoft.de),
Evgenii Davidov (dado korolev-net.ru)
PR: kern/144564
Configurations still affected: with options FLOWTABLE
Modified:
stable/8/sys/net/if_llatbl.c
stable/8/sys/netinet/if_ether.c
stable/8/sys/netinet/in.c
stable/8/sys/netinet6/in6.c
stable/8/sys/netinet6/nd6.c
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/xen/xenpci/ (props changed)
stable/8/sys/geom/sched/ (props changed)
Modified: stable/8/sys/net/if_llatbl.c
==============================================================================
--- stable/8/sys/net/if_llatbl.c Wed Apr 21 19:48:40 2010 (r207012)
+++ stable/8/sys/net/if_llatbl.c Wed Apr 21 19:51:22 2010 (r207013)
@@ -170,9 +170,12 @@ lltable_free(struct lltable *llt)
for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
+ int canceled;
- callout_drain(&lle->la_timer);
+ canceled = callout_drain(&lle->la_timer);
LLE_WLOCK(lle);
+ if (canceled)
+ LLE_REMREF(lle);
llentry_free(lle);
}
}
Modified: stable/8/sys/netinet/if_ether.c
==============================================================================
--- stable/8/sys/netinet/if_ether.c Wed Apr 21 19:48:40 2010 (r207012)
+++ stable/8/sys/netinet/if_ether.c Wed Apr 21 19:51:22 2010 (r207013)
@@ -180,6 +180,8 @@ arptimer(void *arg)
else {
if (!callout_pending(&lle->la_timer) &&
callout_active(&lle->la_timer)) {
+ callout_stop(&lle->la_timer);
+ LLE_REMREF(lle);
(void) llentry_free(lle);
ARPSTAT_INC(timeouts);
}
@@ -382,9 +384,14 @@ retry:
EHOSTUNREACH : EHOSTDOWN;
if (renew) {
+ int canceled;
+
LLE_ADDREF(la);
la->la_expire = time_second + V_arpt_down;
- callout_reset(&la->la_timer, hz * V_arpt_down, arptimer, la);
+ canceled = callout_reset(&la->la_timer, hz * V_arpt_down,
+ arptimer, la);
+ if (canceled)
+ LLE_REMREF(la);
la->la_asked++;
LLE_WUNLOCK(la);
arprequest(ifp, NULL, &SIN(dst)->sin_addr,
@@ -694,9 +701,14 @@ match:
la->la_flags |= LLE_VALID;
if (!(la->la_flags & LLE_STATIC)) {
+ int canceled;
+
+ LLE_ADDREF(la);
la->la_expire = time_second + V_arpt_keep;
- callout_reset(&la->la_timer, hz * V_arpt_keep,
- arptimer, la);
+ canceled = callout_reset(&la->la_timer,
+ hz * V_arpt_keep, arptimer, la);
+ if (canceled)
+ LLE_REMREF(la);
}
la->la_asked = 0;
la->la_preempt = V_arp_maxtries;
Modified: stable/8/sys/netinet/in.c
==============================================================================
--- stable/8/sys/netinet/in.c Wed Apr 21 19:48:40 2010 (r207012)
+++ stable/8/sys/netinet/in.c Wed Apr 21 19:51:22 2010 (r207013)
@@ -1357,8 +1357,12 @@ in_lltable_prefix_free(struct lltable *l
if (IN_ARE_MASKED_ADDR_EQUAL((struct sockaddr_in *)L3_ADDR(lle),
pfx, msk)) {
- callout_drain(&lle->la_timer);
+ int canceled;
+
+ canceled = callout_drain(&lle->la_timer);
LLE_WLOCK(lle);
+ if (canceled)
+ LLE_REMREF(lle);
llentry_free(lle);
}
}
Modified: stable/8/sys/netinet6/in6.c
==============================================================================
--- stable/8/sys/netinet6/in6.c Wed Apr 21 19:48:40 2010 (r207012)
+++ stable/8/sys/netinet6/in6.c Wed Apr 21 19:51:22 2010 (r207013)
@@ -2337,8 +2337,12 @@ in6_lltable_prefix_free(struct lltable *
&((struct sockaddr_in6 *)L3_ADDR(lle))->sin6_addr,
&pfx->sin6_addr,
&msk->sin6_addr)) {
- callout_drain(&lle->la_timer);
+ int canceled;
+
+ canceled = callout_drain(&lle->la_timer);
LLE_WLOCK(lle);
+ if (canceled)
+ LLE_REMREF(lle);
llentry_free(lle);
}
}
Modified: stable/8/sys/netinet6/nd6.c
==============================================================================
--- stable/8/sys/netinet6/nd6.c Wed Apr 21 19:48:40 2010 (r207012)
+++ stable/8/sys/netinet6/nd6.c Wed Apr 21 19:51:22 2010 (r207013)
@@ -1124,6 +1124,7 @@ nd6_free(struct llentry *ln, int gc)
ifp = ln->lle_tbl->llt_ifp;
IF_AFDATA_LOCK(ifp);
LLE_WLOCK(ln);
+ LLE_REMREF(ln);
llentry_free(ln);
IF_AFDATA_UNLOCK(ifp);
More information about the svn-src-stable-8
mailing list