On 21 June 2014 15:36, Alexandr Nedvedicky <alexandr.nedvedi...@oracle.com> wrote: > Hello, > > I'm not sure it is the right place to submit patches. Let me know if there is > better/more appropriate address for this. > > during our testing we've found the once rules are not removed, > when used in main anchor. >
Correct. I've addedd the ruleset pointer check to prevent that shortly before the release since it caused panics... > during debugging we found the rules in main anchor have member anchor set to > NULL (pf_rule::anchor). This makes pf_purge_rule() function to bail out > to early without removing the rule from ruleset. > > patch below fixed problem for us. > However, this solution is not correct for us. Perhaps you have some other changes in your tree to make it work. > Index: pf_ioctl.c > =================================================================== > RCS file: /cvs/src/sys/net/pf_ioctl.c,v > retrieving revision 1.272 > diff -u -r1.272 pf_ioctl.c > --- pf_ioctl.c 22 Apr 2014 14:41:03 -0000 1.272 > +++ pf_ioctl.c 20 Jun 2014 14:26:22 -0000 > @@ -312,7 +312,7 @@ > { > u_int32_t nr; > > - if (ruleset == NULL || ruleset->anchor == NULL) > + if (ruleset == NULL) > return; > ruleset->anchor is useless since nothing really checks for it if ruleset is NULL. > pf_rm_rule(ruleset->rules.active.ptr, rule); > @@ -325,7 +325,10 @@ > ruleset->rules.active.ticket++; > > pf_calc_skip_steps(ruleset->rules.active.ptr); > - pf_remove_if_empty_ruleset(ruleset); > + > + if (ruleset != &pf_main_ruleset) { > + pf_remove_if_empty_ruleset(ruleset); > + } > } > You don't need to check ruleset against &pf_main_ruleset since the first thing pf_remove_if_empty_ruleset does is bail if ruleset == &pf_main_ruleset. This bit confused me quite a bit. What really is a problem for us is that when pf_purge_rule is called on a main ruleset from pf_test_rule the first argument (ruleset) is NULL and not &pf_main_ruleset, which would be sensible. The only other user of it, AFAICT, is pflog_packet but it checks for ruleset->anchor before it does it's thing. I don't see any reason why we can't start our rule set iteration with 'ruleset' set to &pf_main_ruleset (regress tests agree). OK? diff --git sys/net/pf.c sys/net/pf.c index 71f85d1..562901d 100644 --- sys/net/pf.c +++ sys/net/pf.c @@ -3163,10 +3163,11 @@ pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm, } break; #endif /* INET6 */ } + ruleset = &pf_main_ruleset; r = TAILQ_FIRST(pf_main_ruleset.rules.active.ptr); while (r != NULL) { r->evaluations++; PF_TEST_ATTRIB((pfi_kif_match(r->kif, pd->kif) == r->ifnot), r->skip[PF_SKIP_IFP].ptr); diff --git sys/net/pf_ioctl.c sys/net/pf_ioctl.c index 5ad762c..86e987f 100644 --- sys/net/pf_ioctl.c +++ sys/net/pf_ioctl.c @@ -308,24 +308,19 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) } void pf_purge_rule(struct pf_ruleset *ruleset, struct pf_rule *rule) { - u_int32_t nr; + u_int32_t nr = 0; - if (ruleset == NULL || ruleset->anchor == NULL) - return; + KASSERT(ruleset != NULL && rule != NULL); pf_rm_rule(ruleset->rules.active.ptr, rule); ruleset->rules.active.rcount--; - - nr = 0; 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); } u_int16_t