git: bfeef0d32a00 - main - pf: fix pfi_ifnet leak on interface removal

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Wed, 14 Dec 2022 09:20:07 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=bfeef0d32a0036bf6bec93a439e0466efe6f4482

commit bfeef0d32a0036bf6bec93a439e0466efe6f4482
Author:     Nick Reilly <nreilly@blackberry.com>
AuthorDate: 2022-11-30 14:19:44 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-12-14 09:19:01 +0000

    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
---
 sys/net/if.c           |  3 +--
 sys/netpfil/pf/pf_if.c | 23 ++++++++++++++++++-----
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/sys/net/if.c b/sys/net/if.c
index 7cbb750d3ab1..970d1398f870 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -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);
 }
 
 /*
diff --git a/sys/netpfil/pf/pf_if.c b/sys/netpfil/pf/pf_if.c
index f572d80c219f..71bd215d3d24 100644
--- a/sys/netpfil/pf/pf_if.c
+++ b/sys/netpfil/pf/pf_if.c
@@ -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();
 }