git: a3d974082549 - main - pf: make sure the rule tree is allocated in DIOCCHANGERULE
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 30 May 2022 14:10:24 UTC
The branch main has been updated by mjg: URL: https://cgit.FreeBSD.org/src/commit/?id=a3d9740825499c8a495261e09b7f9e49f6b4ac81 commit a3d9740825499c8a495261e09b7f9e49f6b4ac81 Author: Mateusz Guzik <mjg@FreeBSD.org> AuthorDate: 2022-05-27 22:15:34 +0000 Commit: Mateusz Guzik <mjg@FreeBSD.org> CommitDate: 2022-05-30 14:09:53 +0000 pf: make sure the rule tree is allocated in DIOCCHANGERULE Original patch by: peter Sponsored by: Rubicon Communications, LLC ("Netgate") --- sys/netpfil/pf/pf_ioctl.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index 5185e457867e..745b9b69060b 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -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);