mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2025-01-01 00:18:15 +01:00
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 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
This commit is contained in:
parent
3c7ae7bf67
commit
becba438d2
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
@ -696,9 +703,14 @@ match:
|
||||
EVENTHANDLER_INVOKE(arp_update_event, la);
|
||||
|
||||
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;
|
||||
|
@ -1357,8 +1357,12 @@ in_lltable_prefix_free(struct lltable *llt,
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -2344,8 +2344,12 @@ in6_lltable_prefix_free(struct lltable *llt,
|
||||
&((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);
|
||||
}
|
||||
}
|
||||
|
@ -1125,6 +1125,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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user