Hello Klemens.

I took a closer look at your change and related area.  Below is an alternate
way to fix the bug you've found.

there are few details worth to note:

    ptr_array matters to main ruleset only, because it is the only 
    ruleset covered by MD5 sum for pfsync.

    it looks like we should also recompute the MD5sum if we remove the rule
    from the main ruleset 

my diff introduces a new member of pr_ruleset structure, which keeps the
array size so we can pass it to free(9f) later.

I have no pfsync deployment readily available for testing. Will be glad
if you can give my diff a try.

thanks a lot
regards
sashan

--------8<--------------8<--------------8<-----------------8<-------
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index a486745bc1c..00a4f70e7db 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -332,8 +332,32 @@ pf_purge_rule(struct pf_rule *rule)
 
        pf_rm_rule(ruleset->rules.active.ptr, rule);
        ruleset->rules.active.rcount--;
-       TAILQ_FOREACH(rule, ruleset->rules.active.ptr, entries)
-               rule->nr = nr++;
+
+       /*
+        * pf_chksum calculation is copied and modified from
+        * pf_setup_pfsync_matching(), which is part of ruleset commit
+        * operation.
+        */
+       if (ruleset == &pf_main_ruleset) {
+               MD5_CTX         ctx;
+               u_int8_t        digest[PF_MD5_DIGEST_LENGTH];
+
+               MD5Init(&ctx);
+
+               TAILQ_FOREACH(rule, ruleset->rules.active.ptr, entries) {
+                       rule->nr = nr++;
+                       pf_hash_rule(&ctx, rule);
+                       ruleset->rules.active.ptr_array[rule->nr] = rule;
+               }
+
+               MD5Final(digest, &ctx);
+               memcpy(pf_status.pf_chksum, digest, 
sizeof(pf_status.pf_chksum));
+       } else {
+               TAILQ_FOREACH(rule, ruleset->rules.active.ptr, entries) {
+                       rule->nr = nr++;
+               }
+       }
+
        ruleset->rules.active.ticket++;
        pf_calc_skip_steps(ruleset->rules.active.ptr);
        pf_remove_if_empty_ruleset(ruleset);
@@ -804,6 +828,7 @@ pf_commit_rules(u_int32_t ticket, char *anchor)
 {
        struct pf_ruleset       *rs;
        struct pf_rule          *rule, **old_array;
+       size_t                  old_array_sz;
        struct pf_rulequeue     *old_rules;
        int                      error;
        u_int32_t                old_rcount;
@@ -827,13 +852,16 @@ pf_commit_rules(u_int32_t ticket, char *anchor)
        old_rules = rs->rules.active.ptr;
        old_rcount = rs->rules.active.rcount;
        old_array = rs->rules.active.ptr_array;
+       old_array_sz = rs->rules.active.array_sz;
 
        rs->rules.active.ptr = rs->rules.inactive.ptr;
        rs->rules.active.ptr_array = rs->rules.inactive.ptr_array;
        rs->rules.active.rcount = rs->rules.inactive.rcount;
+       rs->rules.active.array_sz = rs->rules.inactive.array_sz;
        rs->rules.inactive.ptr = old_rules;
        rs->rules.inactive.ptr_array = old_array;
        rs->rules.inactive.rcount = old_rcount;
+       rs->rules.inactive.array_sz = old_array_sz;
 
        rs->rules.active.ticket = rs->rules.inactive.ticket;
        pf_calc_skip_steps(rs->rules.active.ptr);
@@ -843,10 +871,12 @@ pf_commit_rules(u_int32_t ticket, char *anchor)
        while ((rule = TAILQ_FIRST(old_rules)) != NULL)
                pf_rm_rule(old_rules, rule);
        if (rs->rules.inactive.ptr_array)
-               free(rs->rules.inactive.ptr_array, M_TEMP, 0);
+               free(rs->rules.inactive.ptr_array, M_TEMP,
+                   rs->rules.inactive.array_sz);
        rs->rules.inactive.ptr_array = NULL;
        rs->rules.inactive.rcount = 0;
        rs->rules.inactive.open = 0;
+       rs->rules.inactive.array_sz = 0;
        pf_remove_if_empty_ruleset(rs);
 
        /* queue defs only in the main ruleset */
@@ -864,10 +894,14 @@ pf_setup_pfsync_matching(struct pf_ruleset *rs)
 
        MD5Init(&ctx);
        if (rs->rules.inactive.ptr_array)
-               free(rs->rules.inactive.ptr_array, M_TEMP, 0);
+               free(rs->rules.inactive.ptr_array, M_TEMP,
+                   rs->rules.inactive.array_sz);
        rs->rules.inactive.ptr_array = NULL;
+       rs->rules.inactive.array_sz = 0;
 
        if (rs->rules.inactive.rcount) {
+               rs->rules.inactive.array_sz =
+                   rs->rules.inactive.rcount * sizeof(caddr_t);
                rs->rules.inactive.ptr_array =
                    mallocarray(rs->rules.inactive.rcount, sizeof(caddr_t),
                    M_TEMP, M_NOWAIT);
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index f06a1fa0e07..acdafcbc971 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -926,6 +926,7 @@ struct pf_ruleset {
                        struct pf_rule          **ptr_array;
                        u_int32_t                rcount;
                        u_int32_t                ticket;
+                       size_t                   array_sz;
                        int                      open;
                }                        active, inactive;
        }                        rules;

Reply via email to