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);