git: 1a7b74d3125f - main - ipfw: in a vnet destructor use NET_EPOCH_WAIT()

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Sat, 17 Jan 2026 04:09:25 UTC
The branch main has been updated by glebius:

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

commit 1a7b74d3125fef50a6d2dcc4442c80457c8d32e1
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2026-01-17 03:57:03 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2026-01-17 04:09:02 +0000

    ipfw: in a vnet destructor use NET_EPOCH_WAIT()
    
    The lock grab & drop predates epoch(9) introduction to the network
    stack and it doesn't provide a true guarantee that all threads that
    may use ipfw configuration have finished.  Also the lock prevented
    from sleepable operations when freeing the rules.
---
 sys/netpfil/ipfw/ip_fw2.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
index 5d5aeb7c2746..7c47a97e4953 100644
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -3731,12 +3731,14 @@ vnet_ipfw_uninit(const void *unused)
 
 	V_ipfw_vnet_ready = 0; /* tell new callers to go away */
 	/*
-	 * disconnect from ipv4, ipv6, layer2 and sockopt.
-	 * Then grab, release and grab again the WLOCK so we make
-	 * sure the update is propagated and nobody will be in.
+	 * Disconnect from ipv4, ipv6, layer2 and sockopt.  pfil(9) hook
+	 * removal is synchronized by the net epoch, but our destructors
+	 * free the memory immediately, thus we need for the epoch sections
+	 * to complete.
 	 */
 	ipfw_detach_hooks();
 	V_ip_fw_ctl_ptr = NULL;
+	NET_EPOCH_WAIT();
 
 	last = IS_DEFAULT_VNET(curvnet) ? 1 : 0;
 
@@ -3745,12 +3747,10 @@ vnet_ipfw_uninit(const void *unused)
 	ipfw_dyn_uninit(0);	/* run the callout_drain */
 
 	reap = NULL;
-	IPFW_WLOCK(chain);
 	for (i = 0; i < chain->n_rules; i++)
 		ipfw_reap_add(chain, &reap, chain->map[i]);
 	free(chain->map, M_IPFW);
 	ipfw_destroy_skipto_cache(chain);
-	IPFW_WUNLOCK(chain);
 	IPFW_UH_WUNLOCK(chain);
 	ipfw_destroy_tables(chain, last);
 	ipfw_eaction_uninit(chain, last);