pf: fix pfi_ifnet leak on interface removal

The detach of the interface and group were leaving pfi_ifnet memory
behind. Check if the kif still has references, and clean it up if it
doesn't

On interface detach, the group deletion was notified first and then a
change notification was sent. This would recreate the group in the kif
layer. Reorder the change to before the delete.

PR:		257218
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D37569
This commit is contained in:
Nick Reilly 2022-11-30 15:19:44 +01:00 committed by Kristof Provost
parent e6fc01f6be
commit bfeef0d32a
2 changed files with 19 additions and 7 deletions

View File

@ -1545,14 +1545,13 @@ _if_delgroup_locked(struct ifnet *ifp, struct ifg_list *ifgl,
IFNET_WUNLOCK();
epoch_wait_preempt(net_epoch_preempt);
EVENTHANDLER_INVOKE(group_change_event, groupname);
if (freeifgl) {
EVENTHANDLER_INVOKE(group_detach_event, ifgl->ifgl_group);
free(ifgl->ifgl_group, M_TEMP);
}
free(ifgm, M_TEMP);
free(ifgl, M_TEMP);
EVENTHANDLER_INVOKE(group_change_event, groupname);
}
/*

View File

@ -364,14 +364,11 @@ pfi_kkif_ref(struct pfi_kkif *kif)
kif->pfik_rulerefs++;
}
void
pfi_kkif_unref(struct pfi_kkif *kif)
static void
pfi_kkif_remove_if_unref(struct pfi_kkif *kif)
{
PF_RULES_WASSERT();
KASSERT(kif->pfik_rulerefs > 0, ("%s: %p has zero refs", __func__, kif));
kif->pfik_rulerefs--;
if (kif->pfik_rulerefs > 0)
return;
@ -391,6 +388,18 @@ pfi_kkif_unref(struct pfi_kkif *kif)
mtx_unlock(&pfi_unlnkdkifs_mtx);
}
void
pfi_kkif_unref(struct pfi_kkif *kif)
{
PF_RULES_WASSERT();
KASSERT(kif->pfik_rulerefs > 0, ("%s: %p has zero refs", __func__, kif));
kif->pfik_rulerefs--;
pfi_kkif_remove_if_unref(kif);
}
void
pfi_kkif_purge(void)
{
@ -1039,6 +1048,8 @@ pfi_detach_ifnet_event(void *arg __unused, struct ifnet *ifp)
#ifdef ALTQ
pf_altq_ifnet_event(ifp, 1);
#endif
pfi_kkif_remove_if_unref(kif);
PF_RULES_WUNLOCK();
NET_EPOCH_EXIT(et);
}
@ -1099,6 +1110,8 @@ pfi_detach_group_event(void *arg __unused, struct ifg_group *ifg)
kif->pfik_group = NULL;
ifg->ifg_pf_kif = NULL;
pfi_kkif_remove_if_unref(kif);
PF_RULES_WUNLOCK();
}