git: 386b1a033c4d - main - pf: allocate krule->timestamp in pf_krule_alloc()

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Tue, 17 May 2022 14:00:38 UTC
The branch main has been updated by kp:

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

commit 386b1a033c4d7345efd378b47cb637d4fb709020
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2022-05-17 12:41:25 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-05-17 13:55:08 +0000

    pf: allocate krule->timestamp in pf_krule_alloc()
    
    There are three calls which can allocate a new rule. DIOCADDRULE,
    DIOCADDRULENV and DIOCCHANGERULE. The first two call pf_ioctl_addrule(),
    but DIOCCHANGERULE does not. As a result rules created through
    DIOCCHANGERULE do not have the timestamp per-cpu memory allocated, and
    we panic when the rule is exported with pf_krule_to_nvrule().
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf_ioctl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 8c3b9a423af1..5185e457867e 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -1771,6 +1771,7 @@ pf_krule_alloc(void)
 
 	rule = malloc(sizeof(struct pf_krule), M_PFRULE, M_WAITOK | M_ZERO);
 	mtx_init(&rule->rpool.mtx, "pf_krule_pool", NULL, MTX_DEF);
+	rule->timestamp = uma_zalloc_pcpu(pcpu_zone_4, M_WAITOK | M_ZERO);
 	return (rule);
 }
 
@@ -2134,7 +2135,6 @@ pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
 	rule->states_cur = counter_u64_alloc(M_WAITOK);
 	rule->states_tot = counter_u64_alloc(M_WAITOK);
 	rule->src_nodes = counter_u64_alloc(M_WAITOK);
-	rule->timestamp = uma_zalloc_pcpu(pcpu_zone_4, M_WAITOK | M_ZERO);
 	rule->cuid = td->td_ucred->cr_ruid;
 	rule->cpid = td->td_proc ? td->td_proc->p_pid : 0;
 	TAILQ_INIT(&rule->rpool.list);
@@ -3412,7 +3412,7 @@ DIOCGETRULENV_error:
 			newrule = pf_krule_alloc();
 			error = pf_rule_to_krule(&pcr->rule, newrule);
 			if (error != 0) {
-				free(newrule, M_PFRULE);
+				pf_krule_free(newrule);
 				break;
 			}