summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2026-01-16 19:57:03 -0800
committerGleb Smirnoff <glebius@FreeBSD.org>2026-01-16 20:09:02 -0800
commit1a7b74d3125fef50a6d2dcc4442c80457c8d32e1 (patch)
tree93293b5d666bb05a8477de21633bf5cade0cfa66 /sys
parent6dc12ecfb268d2d043f9415156d475278f3f714b (diff)
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.
Diffstat (limited to 'sys')
-rw-r--r--sys/netpfil/ipfw/ip_fw2.c10
1 files 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);