pf: make sure the rule tree is allocated in DIOCCHANGERULE

Original patch by:	peter
Sponsored by:	Rubicon Communications, LLC ("Netgate")
This commit is contained in:
Mateusz Guzik 2022-05-28 00:15:34 +02:00
parent 81ffb45f02
commit a3d9740825

@ -1152,6 +1152,25 @@ out:
}
#endif /* ALTQ */
static struct pf_krule_global *
pf_rule_tree_alloc(int flags)
{
struct pf_krule_global *tree;
tree = malloc(sizeof(struct pf_krule_global), M_TEMP, flags);
if (tree == NULL)
return (NULL);
RB_INIT(tree);
return (tree);
}
static void
pf_rule_tree_free(struct pf_krule_global *tree)
{
free(tree, M_TEMP);
}
static int
pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
{
@ -1163,16 +1182,15 @@ pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
return (EINVAL);
tree = malloc(sizeof(struct pf_krule_global), M_TEMP, M_NOWAIT);
tree = pf_rule_tree_alloc(M_NOWAIT);
if (tree == NULL)
return (ENOMEM);
RB_INIT(tree);
rs = pf_find_or_create_kruleset(anchor);
if (rs == NULL) {
free(tree, M_TEMP);
return (EINVAL);
}
free(rs->rules[rs_num].inactive.tree, M_TEMP);
pf_rule_tree_free(rs->rules[rs_num].inactive.tree);
rs->rules[rs_num].inactive.tree = tree;
while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
@ -3455,6 +3473,22 @@ DIOCGETRULENV_error:
if (rs_num >= PF_RULESET_MAX)
ERROUT(EINVAL);
/*
* XXXMJG: there is no guarantee that the ruleset was
* created by the usual route of calling DIOCXBEGIN.
* As a result it is possible the rule tree will not
* be allocated yet. Hack around it by doing it here.
* Note it is fine to let the tree persist in case of
* error as it will be freed down the road on future
* updates (if need be).
*/
if (ruleset->rules[rs_num].active.tree == NULL) {
ruleset->rules[rs_num].active.tree = pf_rule_tree_alloc(M_NOWAIT);
if (ruleset->rules[rs_num].active.tree == NULL) {
ERROUT(ENOMEM);
}
}
if (pcr->action == PF_CHANGE_GET_TICKET) {
pcr->ticket = ++ruleset->rules[rs_num].active.ticket;
ERROUT(0);