On 25/01/17(Wed) 09:53, Sebastian Benoit wrote:
> Hi,
>
> this removes the pf_consistency_lock and protects the users with NET_LOCK()
>
> I ran into a crash when using pfctl -k, and mpi suggested this change (and
> likes the diff).
The reason I suggested this diff is that pfioctl() will need the
NET_LOCK() anyway. So better keep things simple until we're going to
redesign PF for a MP world.
Note that the crash benno@ talked about is just for pflow(4) users.
ok mpi@
> diff --git sys/net/pf.c sys/net/pf.c
> index 2ae434e405d..a8ade533484 100644
> --- sys/net/pf.c
> +++ sys/net/pf.c
> @@ -1154,26 +1154,20 @@ pf_state_export(struct pfsync_state *sp, struct
> pf_state *st)
> /* END state table stuff */
>
> void
> -pf_purge_expired_rules(int locked)
> +pf_purge_expired_rules(void)
> {
> struct pf_rule *r;
>
> + NET_ASSERT_LOCKED();
> +
> if (SLIST_EMPTY(&pf_rule_gcl))
> return;
>
> - if (!locked)
> - rw_enter_write(&pf_consistency_lock);
> - else
> - rw_assert_wrlock(&pf_consistency_lock);
> -
> while ((r = SLIST_FIRST(&pf_rule_gcl)) != NULL) {
> SLIST_REMOVE(&pf_rule_gcl, r, pf_rule, gcle);
> KASSERT(r->rule_flag & PFRULE_EXPIRED);
> pf_purge_rule(r);
> }
> -
> - if (!locked)
> - rw_exit_write(&pf_consistency_lock);
> }
>
> void
> @@ -1194,7 +1188,7 @@ pf_purge_thread(void *v)
> if (++nloops >= pf_default_rule.timeout[PFTM_INTERVAL]) {
> pf_purge_expired_fragments();
> pf_purge_expired_src_nodes(0);
> - pf_purge_expired_rules(0);
> + pf_purge_expired_rules();
> nloops = 0;
> }
>
> @@ -1241,27 +1235,21 @@ pf_state_expires(const struct pf_state *state)
> }
>
> void
> -pf_purge_expired_src_nodes(int waslocked)
> +pf_purge_expired_src_nodes(void)
> {
> struct pf_src_node *cur, *next;
> - int locked = waslocked;
> +
> + NET_ASSERT_LOCKED();
>
> for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) {
> next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur);
>
> if (cur->states == 0 && cur->expire <= time_uptime) {
> - if (! locked) {
> - rw_enter_write(&pf_consistency_lock);
> - next = RB_NEXT(pf_src_tree,
> - &tree_src_tracking, cur);
> - locked = 1;
> - }
> + next = RB_NEXT(pf_src_tree,
> + &tree_src_tracking, cur);
> pf_remove_src_node(cur);
> }
> }
> -
> - if (locked && !waslocked)
> - rw_exit_write(&pf_consistency_lock);
> }
>
> void
> @@ -1334,13 +1322,12 @@ pf_remove_divert_state(struct pf_state_key *sk)
> }
> }
>
> -/* callers should hold the write_lock on pf_consistency_lock */
> void
> pf_free_state(struct pf_state *cur)
> {
> struct pf_rule_item *ri;
>
> - splsoftassert(IPL_SOFTNET);
> + NET_ASSERT_LOCKED();
>
> #if NPFSYNC > 0
> if (pfsync_state_in_use(cur))
> @@ -1375,7 +1362,8 @@ pf_purge_expired_states(u_int32_t maxcheck)
> {
> static struct pf_state *cur = NULL;
> struct pf_state *next;
> - int locked = 0;
> +
> + NET_ASSERT_LOCKED();
>
> while (maxcheck--) {
> /* wrap to start of list when we hit the end */
> @@ -1390,25 +1378,14 @@ pf_purge_expired_states(u_int32_t maxcheck)
>
> if (cur->timeout == PFTM_UNLINKED) {
> /* free removed state */
> - if (! locked) {
> - rw_enter_write(&pf_consistency_lock);
> - locked = 1;
> - }
> pf_free_state(cur);
> } else if (pf_state_expires(cur) <= time_uptime) {
> /* remove and free expired state */
> pf_remove_state(cur);
> - if (! locked) {
> - rw_enter_write(&pf_consistency_lock);
> - locked = 1;
> - }
> pf_free_state(cur);
> }
> cur = next;
> }
> -
> - if (locked)
> - rw_exit_write(&pf_consistency_lock);
> }
>
> int
> diff --git sys/net/pf_ioctl.c sys/net/pf_ioctl.c
> index 9b278c907f5..444425c8bd1 100644
> --- sys/net/pf_ioctl.c
> +++ sys/net/pf_ioctl.c
> @@ -111,7 +111,6 @@ void pf_qid2qname(u_int16_t, char
> *);
> void pf_qid_unref(u_int16_t);
>
> struct pf_rule pf_default_rule, pf_default_rule_new;
> -struct rwlock pf_consistency_lock =
> RWLOCK_INITIALIZER("pfcnslk");
>
> struct {
> char statusif[IFNAMSIZ];
> @@ -987,12 +986,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags,
> struct proc *p)
> return (EACCES);
> }
>
> - if (flags & FWRITE)
> - rw_enter_write(&pf_consistency_lock);
> - else
> - rw_enter_read(&pf_consistency_lock);
> -
> - s = splsoftnet();
> + NET_LOCK(s);
> switch (cmd) {
>
> case DIOCSTART:
> @@ -2388,11 +2382,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int
> flags, struct proc *p)
> break;
> }
> fail:
> - splx(s);
> - if (flags & FWRITE)
> - rw_exit_write(&pf_consistency_lock);
> - else
> - rw_exit_read(&pf_consistency_lock);
> + NET_UNLOCK(s);
> return (error);
> }
>
> diff --git sys/net/pf_norm.c sys/net/pf_norm.c
> index 6bf9681e37f..06c8643b5e4 100644
> --- sys/net/pf_norm.c
> +++ sys/net/pf_norm.c
> @@ -176,6 +176,8 @@ pf_purge_expired_fragments(void)
> struct pf_fragment *frag;
> int32_t expire;
>
> + NET_ASSERT_LOCKED();
> +
> expire = time_uptime - pf_default_rule.timeout[PFTM_FRAG];
> while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) {
> if (frag->fr_timeout > expire)
> diff --git sys/net/pfvar.h sys/net/pfvar.h
> index 9896bf82eca..85ce5074657 100644
> --- sys/net/pfvar.h
> +++ sys/net/pfvar.h
> @@ -1614,9 +1614,9 @@ extern void
> pf_tbladdr_remove(struct pf_addr_wrap *);
> extern void pf_tbladdr_copyout(struct pf_addr_wrap *);
> extern void pf_calc_skip_steps(struct pf_rulequeue *);
> extern void pf_purge_thread(void *);
> -extern void pf_purge_expired_src_nodes(int);
> +extern void pf_purge_expired_src_nodes();
> extern void pf_purge_expired_states(u_int32_t);
> -extern void pf_purge_expired_rules(int);
> +extern void pf_purge_expired_rules();
> extern void pf_remove_state(struct pf_state *);
> extern void pf_remove_divert_state(struct pf_state_key *);
> extern void pf_free_state(struct pf_state *);
> @@ -1790,7 +1790,6 @@ int pf_addr_compare(struct pf_addr *,
> struct pf_addr *,
>
> extern struct pf_status pf_status;
> extern struct pool pf_frent_pl, pf_frag_pl;
> -extern struct rwlock pf_consistency_lock;
>
> struct pf_pool_limit {
> void *pp;
>