pf: Register the netlink family only while the vnets are set up

pf_modevent() registers the generic netlink family at MOD_LOAD, before
vnet_pf_init() has set up the state hashes and locks the handlers use,
and pf_unload() unregisters it after vnet_pf_uninit() has torn them
down.  Sending PFNL_CMD_GETSTATES while pf loads or unloads panics in
pf_handle_getstates() on a NULL or freed V_pf_idhash.

Register the family from a SYSINIT ordered after vnet_pf_init(), and
unregister it from the matching SYSUNINIT, before vnet_pf_uninit().

Reviewed by:		kp
Fixes:			2cef62886d ("pf: convert state retrieval to netlink")
MFC after:		1 week
Sponsored by:		Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D60651
This commit is contained in:
R. Christian McDonald committed 2026-10-13 15:22:30 -04:00
1 parent e6dc001d7a
commit 68831d2a2c
1 file changed
+20 -3
+20 -3
View File
@@ -7982,8 +7982,6 @@ pf_unload(void *dummy __unused)
}
sx_xunlock(&pf_end_lock);
pf_nl_unregister();
if (pf_dev != NULL)
destroy_dev(pf_dev);
@@ -8011,6 +8009,26 @@ SYSUNINIT(pf_unload, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND, pf_unload, NULL);
VNET_SYSUNINIT(vnet_pf_uninit, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
vnet_pf_uninit, NULL);
/*
* The netlink handlers use the per-vnet state: register them after
* vnet_pf_init() and unregister them before vnet_pf_uninit().
*/
static void
pf_nl_init(void *unused __unused)
{
pf_nl_register();
}
SYSINIT(pf_nl, SI_SUB_PROTO_FIREWALL, SI_ORDER_FOURTH, pf_nl_init, NULL);
static void
pf_nl_uninit(void *unused __unused)
{
pf_nl_unregister();
}
SYSUNINIT(pf_nl, SI_SUB_PROTO_FIREWALL, SI_ORDER_FOURTH, pf_nl_uninit, NULL);
static int
pf_modevent(module_t mod, int type, void *data)
{
@@ -8019,7 +8037,6 @@ pf_modevent(module_t mod, int type, void *data)
switch(type) {
case MOD_LOAD:
error = pf_load();
pf_nl_register();
break;
case MOD_UNLOAD:
/* Handled in SYSUNINIT(pf_unload) to ensure it's done after