The branch main has been updated by mjg:

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

commit a3d9740825499c8a495261e09b7f9e49f6b4ac81
Author:     Mateusz Guzik <[email protected]>
AuthorDate: 2022-05-27 22:15:34 +0000
Commit:     Mateusz Guzik <[email protected]>
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);

Reply via email to