Hello Klemens,

</snip>
> > the change is fairly large, but mostly mechanical.
> Relocating malloc(9) and pool(9) seems good but other pf_*() calls are
> now locked inconsistently after your diff.
> 
> Given that only reason about "allocations" this is either an oversight
> and should be fixed or you need to provide more explanation.
> 
> See inline for the spots I'm talking about.

    thanks for catching this. there was unfinished clean up in a branch
    I took diff from.

    Currently we need to keep pf_rm_rule() under both locks. The function
    might be calling pf_tag_unref(), pf_dynaddr_remove()... which alter lists,
    which are currently supposed to be protected by PF_LOCK()/NET_LOCK().

    updated diff is below. pf_rm_rule() is being called with both locks held.


thanks and
regards
sashan

--------8<---------------8<---------------8<------------------8<--------
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index ef7d995e5a7..3a75cd05005 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1006,10 +1006,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        return (EACCES);
                }
 
-       NET_LOCK();
        switch (cmd) {
 
        case DIOCSTART:
+               NET_LOCK();
                PF_LOCK();
                if (pf_status.running)
                        error = EEXIST;
@@ -1025,9 +1025,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        DPFPRINTF(LOG_NOTICE, "pf: started");
                }
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
 
        case DIOCSTOP:
+               NET_LOCK();
                PF_LOCK();
                if (!pf_status.running)
                        error = ENOENT;
@@ -1038,6 +1040,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        DPFPRINTF(LOG_NOTICE, "pf: stopped");
                }
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
 
        case DIOCGETQUEUES: {
@@ -1045,6 +1048,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                struct pf_queuespec     *qs;
                u_int32_t                nr = 0;
 
+               NET_LOCK();
                PF_LOCK();
                pq->ticket = pf_main_ruleset.rules.active.ticket;
 
@@ -1056,6 +1060,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                }
                pq->nr = nr;
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1064,10 +1069,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                struct pf_queuespec     *qs;
                u_int32_t                nr = 0;
 
+               NET_LOCK();
                PF_LOCK();
                if (pq->ticket != pf_main_ruleset.rules.active.ticket) {
                        error = EBUSY;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
 
@@ -1078,10 +1085,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                if (qs == NULL) {
                        error = EBUSY;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                memcpy(&pq->queue, qs, sizeof(pq->queue));
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1091,10 +1100,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                u_int32_t                nr;
                int                      nbytes;
 
+               NET_LOCK();
                PF_LOCK();
                if (pq->ticket != pf_main_ruleset.rules.active.ticket) {
                        error = EBUSY;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                nbytes = pq->nbytes;
@@ -1107,6 +1118,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                if (qs == NULL) {
                        error = EBUSY;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                memcpy(&pq->queue, qs, sizeof(pq->queue));
@@ -1121,6 +1133,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                if (error == 0)
                        pq->nbytes = nbytes;
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1128,38 +1141,44 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                struct pfioc_queue      *q = (struct pfioc_queue *)addr;
                struct pf_queuespec     *qs;
 
-               PF_LOCK();
-               if (q->ticket != pf_main_ruleset.rules.inactive.ticket) {
-                       error = EBUSY;
-                       PF_UNLOCK();
-                       break;
-               }
                qs = pool_get(&pf_queue_pl, PR_WAITOK|PR_LIMITFAIL|PR_ZERO);
                if (qs == NULL) {
                        error = ENOMEM;
+                       break;
+               }
+
+               NET_LOCK();
+               PF_LOCK();
+               if (q->ticket != pf_main_ruleset.rules.inactive.ticket) {
+                       error = EBUSY;
                        PF_UNLOCK();
+                       NET_UNLOCK();
+                       pool_put(&pf_queue_pl, qs);
                        break;
                }
                memcpy(qs, &q->queue, sizeof(*qs));
                qs->qid = pf_qname2qid(qs->qname, 1);
                if (qs->qid == 0) {
-                       pool_put(&pf_queue_pl, qs);
                        error = EBUSY;
                        PF_UNLOCK();
+                       NET_UNLOCK();
+                       pool_put(&pf_queue_pl, qs);
                        break;
                }
                if (qs->parent[0] && (qs->parent_qid =
                    pf_qname2qid(qs->parent, 0)) == 0) {
-                       pool_put(&pf_queue_pl, qs);
                        error = ESRCH;
                        PF_UNLOCK();
+                       NET_UNLOCK();
+                       pool_put(&pf_queue_pl, qs);
                        break;
                }
                qs->kif = pfi_kif_get(qs->ifname);
                if (qs->kif == NULL) {
-                       pool_put(&pf_queue_pl, qs);
                        error = ESRCH;
                        PF_UNLOCK();
+                       NET_UNLOCK();
+                       pool_put(&pf_queue_pl, qs);
                        break;
                }
                /* XXX resolve bw percentage specs */
@@ -1167,6 +1186,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
 
                TAILQ_INSERT_TAIL(pf_queues_inactive, qs, entries);
                PF_UNLOCK();
+               NET_UNLOCK();
 
                break;
        }
@@ -1176,34 +1196,42 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                struct pf_ruleset       *ruleset;
                struct pf_rule          *rule, *tail;
 
+               rule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL|PR_ZERO);
+               if (rule == NULL) {
+                       error = ENOMEM;
+                       break;
+               }
+
+               NET_LOCK();
                PF_LOCK();
                pr->anchor[sizeof(pr->anchor) - 1] = '\0';
                ruleset = pf_find_ruleset(pr->anchor);
                if (ruleset == NULL) {
                        error = EINVAL;
                        PF_UNLOCK();
+                       NET_UNLOCK();
+                       pool_put(&pf_rule_pl, rule);
                        break;
                }
                if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
                        error = EINVAL;
                        PF_UNLOCK();
+                       NET_UNLOCK();
+                       pool_put(&pf_rule_pl, rule);
                        break;
                }
                if (pr->ticket != ruleset->rules.inactive.ticket) {
                        error = EBUSY;
                        PF_UNLOCK();
-                       break;
-               }
-               rule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL|PR_ZERO);
-               if (rule == NULL) {
-                       error = ENOMEM;
-                       PF_UNLOCK();
+                       NET_UNLOCK();
+                       pool_put(&pf_rule_pl, rule);
                        break;
                }
                if ((error = pf_rule_copyin(&pr->rule, rule, ruleset))) {
                        pf_rm_rule(NULL, rule);
                        rule = NULL;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                rule->cuid = p->p_ucred->cr_ruid;
@@ -1223,6 +1251,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        rule = NULL;
                        error = EAFNOSUPPORT;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        goto fail;
                }
                tail = TAILQ_LAST(ruleset->rules.inactive.ptr,
@@ -1258,6 +1287,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                if (error) {
                        pf_rm_rule(NULL, rule);
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                TAILQ_INSERT_TAIL(ruleset->rules.inactive.ptr,
@@ -1265,6 +1295,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                rule->ruleset = ruleset;
                ruleset->rules.inactive.rcount++;
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1273,12 +1304,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                struct pf_ruleset       *ruleset;
                struct pf_rule          *tail;
 
+               NET_LOCK();
                PF_LOCK();
                pr->anchor[sizeof(pr->anchor) - 1] = '\0';
                ruleset = pf_find_ruleset(pr->anchor);
                if (ruleset == NULL) {
                        error = EINVAL;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                tail = TAILQ_LAST(ruleset->rules.active.ptr, pf_rulequeue);
@@ -1288,6 +1321,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        pr->nr = 0;
                pr->ticket = ruleset->rules.active.ticket;
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1297,17 +1331,20 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                struct pf_rule          *rule;
                int                      i;
 
+               NET_LOCK();
                PF_LOCK();
                pr->anchor[sizeof(pr->anchor) - 1] = '\0';
                ruleset = pf_find_ruleset(pr->anchor);
                if (ruleset == NULL) {
                        error = EINVAL;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                if (pr->ticket != ruleset->rules.active.ticket) {
                        error = EBUSY;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                rule = TAILQ_FIRST(ruleset->rules.active.ptr);
@@ -1316,6 +1353,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                if (rule == NULL) {
                        error = EBUSY;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                memcpy(&pr->rule, rule, sizeof(struct pf_rule));
@@ -1333,6 +1371,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                if (pf_anchor_copyout(ruleset, rule, pr)) {
                        error = EBUSY;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                pf_addr_copyout(&pr->rule.src.addr);
@@ -1354,6 +1393,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        rule->states_tot = 0;
                }
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1368,40 +1408,49 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = EINVAL;
                        break;
                }
+
+               newrule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL|PR_ZERO);
+               if (newrule == NULL) {
+                       error = ENOMEM;
+                       break;
+               }
+
+               NET_LOCK();
                PF_LOCK();
                ruleset = pf_find_ruleset(pcr->anchor);
                if (ruleset == NULL) {
                        error = EINVAL;
                        PF_UNLOCK();
+                       NET_UNLOCK();
+                       pool_put(&pf_rule_pl, newrule);
                        break;
                }
 
                if (pcr->action == PF_CHANGE_GET_TICKET) {
                        pcr->ticket = ++ruleset->rules.active.ticket;
                        PF_UNLOCK();
+                       NET_UNLOCK();
+                       pool_put(&pf_rule_pl, newrule);
                        break;
                } else {
                        if (pcr->ticket !=
                            ruleset->rules.active.ticket) {
                                error = EINVAL;
                                PF_UNLOCK();
+                               NET_UNLOCK();
+                               pool_put(&pf_rule_pl, newrule);
                                break;
                        }
                        if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
                                error = EINVAL;
                                PF_UNLOCK();
+                               NET_UNLOCK();
+                               pool_put(&pf_rule_pl, newrule);
                                break;
                        }
                }
 
                if (pcr->action != PF_CHANGE_REMOVE) {
-                       newrule = pool_get(&pf_rule_pl,
-                           PR_WAITOK|PR_LIMITFAIL|PR_ZERO);
-                       if (newrule == NULL) {
-                               error = ENOMEM;
-                               PF_UNLOCK();
-                               break;
-                       }
                        pf_rule_copyin(&pcr->rule, newrule, ruleset);
                        newrule->cuid = p->p_ucred->cr_ruid;
                        newrule->cpid = p->p_p->ps_pid;
@@ -1419,6 +1468,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                                pf_rm_rule(NULL, newrule);
                                error = EAFNOSUPPORT;
                                PF_UNLOCK();
+                               NET_UNLOCK();
                                goto fail;
                        }
 
@@ -1440,6 +1490,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        if (error) {
                                pf_rm_rule(NULL, newrule);
                                PF_UNLOCK();
+                               NET_UNLOCK();
                                break;
                        }
                }
@@ -1458,6 +1509,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                                        pf_rm_rule(NULL, newrule);
                                error = EINVAL;
                                PF_UNLOCK();
+                               NET_UNLOCK();
                                break;
                        }
                }
@@ -1490,6 +1542,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                pf_remove_if_empty_ruleset(ruleset);
 
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1498,6 +1551,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
                u_int                    killed = 0;
 
+               NET_LOCK();
                PF_LOCK();
                PF_STATE_ENTER_WRITE();
                for (s = RB_MIN(pf_state_tree_id, &tree_id); s; s = nexts) {
@@ -1519,6 +1573,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
 #endif /* NPFSYNC > 0 */
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1536,6 +1591,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                if (psk->psk_pfcmp.id) {
                        if (psk->psk_pfcmp.creatorid == 0)
                                psk->psk_pfcmp.creatorid = pf_status.hostid;
+                       NET_LOCK();
                        PF_LOCK();
                        PF_STATE_ENTER_WRITE();
                        if ((s = pf_find_state_byid(&psk->psk_pfcmp))) {
@@ -1544,6 +1600,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        }
                        PF_STATE_EXIT_WRITE();
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
 
@@ -1555,6 +1612,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        key.proto = psk->psk_proto;
                        key.rdomain = psk->psk_rdomain;
 
+                       NET_LOCK();
                        PF_LOCK();
                        PF_STATE_ENTER_WRITE();
                        for (i = 0; i < nitems(dirs); i++) {
@@ -1599,9 +1657,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                                psk->psk_killed = killed;
                        PF_STATE_EXIT_WRITE();
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
 
+               NET_LOCK();
                PF_LOCK();
                PF_STATE_ENTER_WRITE();
                for (s = RB_MIN(pf_state_tree_id, &tree_id); s;
@@ -1651,6 +1711,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                psk->psk_killed = killed;
                PF_STATE_EXIT_WRITE();
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1663,11 +1724,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = EINVAL;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                PF_STATE_ENTER_WRITE();
                error = pfsync_state_import(sp, PFSYNC_SI_IOCTL);
                PF_STATE_EXIT_WRITE();
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 #endif /* NPFSYNC > 0 */
@@ -1681,10 +1744,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                id_key.id = ps->state.id;
                id_key.creatorid = ps->state.creatorid;
 
+               NET_LOCK();
                PF_STATE_ENTER_READ();
                s = pf_find_state_byid(&id_key);
                s = pf_state_ref(s);
                PF_STATE_EXIT_READ();
+               NET_UNLOCK();
                if (s == NULL) {
                        error = ENOENT;
                        break;
@@ -1711,6 +1776,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
 
                p = ps->ps_states;
 
+               NET_LOCK();
                PF_STATE_ENTER_READ();
                state = TAILQ_FIRST(&state_list);
                while (state) {
@@ -1730,6 +1796,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        state = TAILQ_NEXT(state, entry_list);
                }
                PF_STATE_EXIT_READ();
+               NET_UNLOCK();
 
                ps->ps_len = sizeof(struct pfsync_state) * nr;
 
@@ -1739,36 +1806,43 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
 
        case DIOCGETSTATUS: {
                struct pf_status *s = (struct pf_status *)addr;
+               NET_LOCK();
                PF_LOCK();
                memcpy(s, &pf_status, sizeof(struct pf_status));
                pfi_update_status(s->ifname, s);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCSETSTATUSIF: {
                struct pfioc_iface      *pi = (struct pfioc_iface *)addr;
 
+               NET_LOCK();
                PF_LOCK();
                if (pi->pfiio_name[0] == 0) {
                        memset(pf_status.ifname, 0, IFNAMSIZ);
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                strlcpy(pf_trans_set.statusif, pi->pfiio_name, IFNAMSIZ);
                pf_trans_set.mask |= PF_TSET_STATUSIF;
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCCLRSTATUS: {
                struct pfioc_iface      *pi = (struct pfioc_iface *)addr;
 
+               NET_LOCK();
                PF_LOCK();
                /* if ifname is specified, clear counters there only */
                if (pi->pfiio_name[0]) {
                        pfi_update_status(pi->pfiio_name, NULL);
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
 
@@ -1778,6 +1852,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                pf_status.since = getuptime();
 
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1822,10 +1897,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        pf_addrcpy(&key.addr[didx], &pnl->daddr, pnl->af);
                        key.port[didx] = pnl->dport;
 
+                       NET_LOCK();
                        PF_STATE_ENTER_READ();
                        state = pf_find_state_all(&key, direction, &m);
                        state = pf_state_ref(state);
                        PF_STATE_EXIT_READ();
+                       NET_UNLOCK();
 
                        if (m > 1)
                                error = E2BIG;  /* more than one state */
@@ -1853,12 +1930,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = EINVAL;
                        goto fail;
                }
+               NET_LOCK();
                PF_LOCK();
                if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0)
                        pt->seconds = 1;
                pf_default_rule_new.timeout[pt->timeout] = pt->seconds;
                pt->seconds = pf_default_rule.timeout[pt->timeout];
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1869,9 +1948,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = EINVAL;
                        goto fail;
                }
+               NET_LOCK();
                PF_LOCK();
                pt->seconds = pf_default_rule.timeout[pt->timeout];
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1882,48 +1963,57 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = EINVAL;
                        goto fail;
                }
+               NET_LOCK();
                PF_LOCK();
                pl->limit = pf_pool_limits[pl->index].limit;
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCSETLIMIT: {
                struct pfioc_limit      *pl = (struct pfioc_limit *)addr;
 
+               NET_LOCK();
                PF_LOCK();
                if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
                    pf_pool_limits[pl->index].pp == NULL) {
                        error = EINVAL;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        goto fail;
                }
                if (((struct pool *)pf_pool_limits[pl->index].pp)->pr_nout >
                    pl->limit) {
                        error = EBUSY;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        goto fail;
                }
                /* Fragments reference mbuf clusters. */
                if (pl->index == PF_LIMIT_FRAGS && pl->limit > nmbclust) {
                        error = EINVAL;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        goto fail;
                }
 
                pf_pool_limits[pl->index].limit_new = pl->limit;
                pl->limit = pf_pool_limits[pl->index].limit;
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCSETDEBUG: {
                u_int32_t       *level = (u_int32_t *)addr;
 
+               NET_LOCK();
                PF_LOCK();
                pf_trans_set.debug = *level;
                pf_trans_set.mask |= PF_TSET_DEBUG;
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1932,11 +2022,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                struct pf_ruleset       *ruleset;
                struct pf_anchor        *anchor;
 
+               NET_LOCK();
                PF_LOCK();
                pr->path[sizeof(pr->path) - 1] = '\0';
                if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
                        error = EINVAL;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                pr->nr = 0;
@@ -1951,6 +2043,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                                pr->nr++;
                }
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -1960,11 +2053,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                struct pf_anchor        *anchor;
                u_int32_t                nr = 0;
 
+               NET_LOCK();
                PF_LOCK();
                pr->path[sizeof(pr->path) - 1] = '\0';
                if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
                        error = EINVAL;
                        PF_UNLOCK();
+                       NET_UNLOCK();
                        break;
                }
                pr->name[0] = '\0';
@@ -1986,6 +2081,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                                }
                }
                PF_UNLOCK();
+               NET_UNLOCK();
                if (!pr->name[0])
                        error = EBUSY;
                break;
@@ -1998,10 +2094,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
                    io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2012,10 +2110,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size,
                    &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2026,10 +2126,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size,
                    &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2040,10 +2142,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer,
                    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2054,10 +2158,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer,
                    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2068,10 +2174,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size,
                    &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2082,11 +2190,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size,
                    io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
                    &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2097,10 +2207,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
                    io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2111,11 +2223,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer,
                    io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
                    PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2126,11 +2240,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer,
                    io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
                    PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2141,12 +2257,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer,
                    io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
                    &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
                    PFR_FLAG_USERIOCTL, 0);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2157,10 +2275,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer,
                    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2171,10 +2291,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer,
                    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2185,11 +2307,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer,
                    io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
                    PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2200,11 +2324,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer,
                    io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
                    PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2215,27 +2341,25 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer,
                    io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
                    io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCOSFPADD: {
                struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
-               PF_LOCK();
                error = pf_osfp_add(io);
-               PF_UNLOCK();
                break;
        }
 
        case DIOCOSFPGET: {
                struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
-               PF_LOCK();
                error = pf_osfp_get(io);
-               PF_UNLOCK();
                break;
        }
 
@@ -2249,25 +2373,28 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        goto fail;
                }
-               PF_LOCK();
                ioe = malloc(sizeof(*ioe), M_TEMP, M_WAITOK);
                table = malloc(sizeof(*table), M_TEMP, M_WAITOK);
+               NET_LOCK();
+               PF_LOCK();
                pf_default_rule_new = pf_default_rule;
                memset(&pf_trans_set, 0, sizeof(pf_trans_set));
                for (i = 0; i < io->size; i++) {
                        if (copyin(io->array+i, ioe, sizeof(*ioe))) {
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = EFAULT;
-                               PF_UNLOCK();
                                goto fail;
                        }
                        if (strnlen(ioe->anchor, sizeof(ioe->anchor)) ==
                            sizeof(ioe->anchor)) {
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = ENAMETOOLONG;
-                               PF_UNLOCK();
                                goto fail;
                        }
                        switch (ioe->type) {
@@ -2277,39 +2404,44 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                                    sizeof(table->pfrt_anchor));
                                if ((error = pfr_ina_begin(table,
                                    &ioe->ticket, NULL, 0))) {
+                                       PF_UNLOCK();
+                                       NET_UNLOCK();
                                        free(table, M_TEMP, sizeof(*table));
                                        free(ioe, M_TEMP, sizeof(*ioe));
-                                       PF_UNLOCK();
                                        goto fail;
                                }
                                break;
                        case PF_TRANS_RULESET:
                                if ((error = pf_begin_rules(&ioe->ticket,
                                    ioe->anchor))) {
+                                       PF_UNLOCK();
+                                       NET_UNLOCK();
                                        free(table, M_TEMP, sizeof(*table));
                                        free(ioe, M_TEMP, sizeof(*ioe));
-                                       PF_UNLOCK();
                                        goto fail;
                                }
                                break;
                        default:
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = EINVAL;
-                               PF_UNLOCK();
                                goto fail;
                        }
                        if (copyout(ioe, io->array+i, sizeof(io->array[i]))) {
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = EFAULT;
-                               PF_UNLOCK();
                                goto fail;
                        }
                }
+               PF_UNLOCK();
+               NET_UNLOCK();
                free(table, M_TEMP, sizeof(*table));
                free(ioe, M_TEMP, sizeof(*ioe));
-               PF_UNLOCK();
                break;
        }
 
@@ -2323,23 +2455,26 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        goto fail;
                }
-               PF_LOCK();
                ioe = malloc(sizeof(*ioe), M_TEMP, M_WAITOK);
                table = malloc(sizeof(*table), M_TEMP, M_WAITOK);
+               NET_LOCK();
+               PF_LOCK();
                for (i = 0; i < io->size; i++) {
                        if (copyin(io->array+i, ioe, sizeof(*ioe))) {
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = EFAULT;
-                               PF_UNLOCK();
                                goto fail;
                        }
                        if (strnlen(ioe->anchor, sizeof(ioe->anchor)) ==
                            sizeof(ioe->anchor)) {
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = ENAMETOOLONG;
-                               PF_UNLOCK();
                                goto fail;
                        }
                        switch (ioe->type) {
@@ -2349,32 +2484,36 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                                    sizeof(table->pfrt_anchor));
                                if ((error = pfr_ina_rollback(table,
                                    ioe->ticket, NULL, 0))) {
+                                       PF_UNLOCK();
+                                       NET_UNLOCK();
                                        free(table, M_TEMP, sizeof(*table));
                                        free(ioe, M_TEMP, sizeof(*ioe));
-                                       PF_UNLOCK();
                                        goto fail; /* really bad */
                                }
                                break;
                        case PF_TRANS_RULESET:
                                if ((error = pf_rollback_rules(ioe->ticket,
                                    ioe->anchor))) {
+                                       PF_UNLOCK();
+                                       NET_UNLOCK();
                                        free(table, M_TEMP, sizeof(*table));
                                        free(ioe, M_TEMP, sizeof(*ioe));
-                                       PF_UNLOCK();
                                        goto fail; /* really bad */
                                }
                                break;
                        default:
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = EINVAL;
-                               PF_UNLOCK();
                                goto fail; /* really bad */
                        }
                }
+               PF_UNLOCK();
+               NET_UNLOCK();
                free(table, M_TEMP, sizeof(*table));
                free(ioe, M_TEMP, sizeof(*ioe));
-               PF_UNLOCK();
                break;
        }
 
@@ -2389,24 +2528,27 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        goto fail;
                }
-               PF_LOCK();
                ioe = malloc(sizeof(*ioe), M_TEMP, M_WAITOK);
                table = malloc(sizeof(*table), M_TEMP, M_WAITOK);
+               NET_LOCK();
+               PF_LOCK();
                /* first makes sure everything will succeed */
                for (i = 0; i < io->size; i++) {
                        if (copyin(io->array+i, ioe, sizeof(*ioe))) {
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = EFAULT;
-                               PF_UNLOCK();
                                goto fail;
                        }
                        if (strnlen(ioe->anchor, sizeof(ioe->anchor)) ==
                            sizeof(ioe->anchor)) {
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = ENAMETOOLONG;
-                               PF_UNLOCK();
                                goto fail;
                        }
                        switch (ioe->type) {
@@ -2414,10 +2556,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                                rs = pf_find_ruleset(ioe->anchor);
                                if (rs == NULL || !rs->topen || ioe->ticket !=
                                     rs->tticket) {
+                                       PF_UNLOCK();
+                                       NET_UNLOCK();
                                        free(table, M_TEMP, sizeof(*table));
                                        free(ioe, M_TEMP, sizeof(*ioe));
                                        error = EBUSY;
-                                       PF_UNLOCK();
                                        goto fail;
                                }
                                break;
@@ -2427,18 +2570,20 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                                    !rs->rules.inactive.open ||
                                    rs->rules.inactive.ticket !=
                                    ioe->ticket) {
+                                       PF_UNLOCK();
+                                       NET_UNLOCK();
                                        free(table, M_TEMP, sizeof(*table));
                                        free(ioe, M_TEMP, sizeof(*ioe));
                                        error = EBUSY;
-                                       PF_UNLOCK();
                                        goto fail;
                                }
                                break;
                        default:
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = EINVAL;
-                               PF_UNLOCK();
                                goto fail;
                        }
                }
@@ -2450,28 +2595,31 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                for (i = 0; i < PF_LIMIT_MAX; i++) {
                        if (((struct pool *)pf_pool_limits[i].pp)->pr_nout >
                            pf_pool_limits[i].limit_new) {
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = EBUSY;
-                               PF_UNLOCK();
                                goto fail;
                        }
                }
                /* now do the commit - no errors should happen here */
                for (i = 0; i < io->size; i++) {
                        if (copyin(io->array+i, ioe, sizeof(*ioe))) {
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = EFAULT;
-                               PF_UNLOCK();
                                goto fail;
                        }
                        if (strnlen(ioe->anchor, sizeof(ioe->anchor)) ==
                            sizeof(ioe->anchor)) {
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = ENAMETOOLONG;
-                               PF_UNLOCK();
                                goto fail;
                        }
                        switch (ioe->type) {
@@ -2481,26 +2629,29 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                                    sizeof(table->pfrt_anchor));
                                if ((error = pfr_ina_commit(table, ioe->ticket,
                                    NULL, NULL, 0))) {
+                                       PF_UNLOCK();
+                                       NET_UNLOCK();
                                        free(table, M_TEMP, sizeof(*table));
                                        free(ioe, M_TEMP, sizeof(*ioe));
-                                       PF_UNLOCK();
                                        goto fail; /* really bad */
                                }
                                break;
                        case PF_TRANS_RULESET:
                                if ((error = pf_commit_rules(ioe->ticket,
                                    ioe->anchor))) {
+                                       PF_UNLOCK();
+                                       NET_UNLOCK();
                                        free(table, M_TEMP, sizeof(*table));
                                        free(ioe, M_TEMP, sizeof(*ioe));
-                                       PF_UNLOCK();
                                        goto fail; /* really bad */
                                }
                                break;
                        default:
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = EINVAL;
-                               PF_UNLOCK();
                                goto fail; /* really bad */
                        }
                }
@@ -2509,10 +2660,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                            pf_pool_limits[i].limit &&
                            pool_sethardlimit(pf_pool_limits[i].pp,
                            pf_pool_limits[i].limit_new, NULL, 0) != 0) {
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                free(table, M_TEMP, sizeof(*table));
                                free(ioe, M_TEMP, sizeof(*ioe));
                                error = EBUSY;
-                               PF_UNLOCK();
                                goto fail; /* really bad */
                        }
                        pf_pool_limits[i].limit = pf_pool_limits[i].limit_new;
@@ -2528,9 +2680,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                }
                pfi_xcommit();
                pf_trans_set_commit();
+               PF_UNLOCK();
+               NET_UNLOCK();
                free(table, M_TEMP, sizeof(*table));
                free(ioe, M_TEMP, sizeof(*ioe));
-               PF_UNLOCK();
                break;
        }
 
@@ -2540,17 +2693,20 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                u_int32_t                nr = 0;
                size_t                   space = psn->psn_len;
 
+               pstore = malloc(sizeof(*pstore), M_TEMP, M_WAITOK);
+
+               NET_LOCK();
                PF_LOCK();
                if (space == 0) {
                        RB_FOREACH(n, pf_src_tree, &tree_src_tracking)
                                nr++;
                        psn->psn_len = sizeof(struct pf_src_node) * nr;
                        PF_UNLOCK();
+                       NET_UNLOCK();
+                       free(pstore, M_TEMP, sizeof(*pstore));
                        break;
                }
 
-               pstore = malloc(sizeof(*pstore), M_TEMP, M_WAITOK);
-
                p = psn->psn_src_nodes;
                RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
                        int     secs = getuptime(), diff;
@@ -2580,8 +2736,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
 
                        error = copyout(pstore, p, sizeof(*p));
                        if (error) {
-                               free(pstore, M_TEMP, sizeof(*pstore));
                                PF_UNLOCK();
+                               NET_UNLOCK();
+                               free(pstore, M_TEMP, sizeof(*pstore));
                                goto fail;
                        }
                        p++;
@@ -2589,8 +2746,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                }
                psn->psn_len = sizeof(struct pf_src_node) * nr;
 
-               free(pstore, M_TEMP, sizeof(*pstore));
                PF_UNLOCK();
+               NET_UNLOCK();
+               free(pstore, M_TEMP, sizeof(*pstore));
                break;
        }
 
@@ -2598,6 +2756,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                struct pf_src_node      *n;
                struct pf_state         *state;
 
+               NET_LOCK();
                PF_LOCK();
                PF_STATE_ENTER_WRITE();
                RB_FOREACH(state, pf_state_tree_id, &tree_id)
@@ -2607,6 +2766,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        n->expire = 1;
                pf_purge_expired_src_nodes();
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2617,6 +2777,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                    (struct pfioc_src_node_kill *)addr;
                u_int                   killed = 0;
 
+               NET_LOCK();
                PF_LOCK();
                RB_FOREACH(sn, pf_src_tree, &tree_src_tracking) {
                        if (pf_match_addr(psnk->psnk_src.neg,
@@ -2646,12 +2807,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
 
                psnk->psnk_killed = killed;
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCSETHOSTID: {
                u_int32_t       *hostid = (u_int32_t *)addr;
 
+               NET_LOCK();
                PF_LOCK();
                if (*hostid == 0)
                        pf_trans_set.hostid = arc4random();
@@ -2659,13 +2822,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        pf_trans_set.hostid = *hostid;
                pf_trans_set.mask |= PF_TSET_HOSTID;
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCOSFPFLUSH:
-               PF_LOCK();
                pf_osfp_flush();
-               PF_UNLOCK();
                break;
 
        case DIOCIGETIFACES: {
@@ -2675,65 +2837,79 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ENODEV;
                        break;
                }
+               NET_LOCK();
                PF_LOCK();
                error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer,
                    &io->pfiio_size);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCSETIFFLAG: {
                struct pfioc_iface *io = (struct pfioc_iface *)addr;
 
+               NET_LOCK();
                PF_LOCK();
                error = pfi_set_flags(io->pfiio_name, io->pfiio_flags);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCCLRIFFLAG: {
                struct pfioc_iface *io = (struct pfioc_iface *)addr;
 
+               NET_LOCK();
                PF_LOCK();
                error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCSETREASS: {
                u_int32_t       *reass = (u_int32_t *)addr;
 
+               NET_LOCK();
                PF_LOCK();
                pf_trans_set.reass = *reass;
                pf_trans_set.mask |= PF_TSET_REASS;
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCSETSYNFLWATS: {
                struct pfioc_synflwats *io = (struct pfioc_synflwats *)addr;
 
+               NET_LOCK();
                PF_LOCK();
                error = pf_syncookies_setwats(io->hiwat, io->lowat);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCGETSYNFLWATS: {
                struct pfioc_synflwats *io = (struct pfioc_synflwats *)addr;
 
+               NET_LOCK();
                PF_LOCK();
                error = pf_syncookies_getwats(io);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
        case DIOCSETSYNCOOKIES: {
                u_int8_t        *mode = (u_int8_t *)addr;
 
+               NET_LOCK();
                PF_LOCK();
                error = pf_syncookies_setmode(*mode);
                PF_UNLOCK();
+               NET_UNLOCK();
                break;
        }
 
@@ -2742,7 +2918,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                break;
        }
 fail:
-       NET_UNLOCK();
        return (error);
 }
 
diff --git a/sys/net/pf_osfp.c b/sys/net/pf_osfp.c
index 5e04d372330..1f2072870ef 100644
--- a/sys/net/pf_osfp.c
+++ b/sys/net/pf_osfp.c
@@ -307,6 +307,7 @@ pf_osfp_flush(void)
        struct pf_os_fingerprint *fp;
        struct pf_osfp_entry *entry;
 
+       PF_LOCK();
        while ((fp = SLIST_FIRST(&pf_osfp_list))) {
                SLIST_REMOVE_HEAD(&pf_osfp_list, fp_next);
                while ((entry = SLIST_FIRST(&fp->fp_oses))) {
@@ -315,6 +316,7 @@ pf_osfp_flush(void)
                }
                pool_put(&pf_osfp_pl, fp);
        }
+       PF_UNLOCK();
 }
 
 
@@ -322,7 +324,7 @@ pf_osfp_flush(void)
 int
 pf_osfp_add(struct pf_osfp_ioctl *fpioc)
 {
-       struct pf_os_fingerprint *fp, fpadd;
+       struct pf_os_fingerprint *fp, *fp_prealloc, fpadd;
        struct pf_osfp_entry *entry;
 
        memset(&fpadd, 0, sizeof(fpadd));
@@ -360,18 +362,31 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
            fpadd.fp_wscale,
            fpioc->fp_os.fp_os);
 
+       entry = pool_get(&pf_osfp_entry_pl, PR_WAITOK|PR_LIMITFAIL);
+       if (entry == NULL)
+               return (ENOMEM);
+
+       fp_prealloc = pool_get(&pf_osfp_pl, PR_WAITOK|PR_ZERO|PR_LIMITFAIL);
+       if (fp == NULL) {
+               pool_put(&pf_osfp_entry_pl, entry);
+               return (ENOMEM);
+       }
+
+       NET_LOCK();
+       PF_LOCK();
        if ((fp = pf_osfp_find_exact(&pf_osfp_list, &fpadd))) {
                 SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
-                       if (PF_OSFP_ENTRY_EQ(entry, &fpioc->fp_os))
+                       if (PF_OSFP_ENTRY_EQ(entry, &fpioc->fp_os)) {
+                               NET_UNLOCK();
+                               PF_UNLOCK();
+                               pool_put(&pf_osfp_entry_pl, entry);
+                               pool_put(&pf_osfp_pl, fp);
                                return (EEXIST);
+                       }
                }
-               if ((entry = pool_get(&pf_osfp_entry_pl,
-                   PR_WAITOK|PR_LIMITFAIL)) == NULL)
-                       return (ENOMEM);
        } else {
-               if ((fp = pool_get(&pf_osfp_pl,
-                   PR_WAITOK|PR_ZERO|PR_LIMITFAIL)) == NULL)
-                       return (ENOMEM);
+               fp = fp_prealloc;
+               fp_prealloc = NULL;
                fp->fp_tcpopts = fpioc->fp_tcpopts;
                fp->fp_wsize = fpioc->fp_wsize;
                fp->fp_psize = fpioc->fp_psize;
@@ -381,11 +396,6 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
                fp->fp_wscale = fpioc->fp_wscale;
                fp->fp_ttl = fpioc->fp_ttl;
                SLIST_INIT(&fp->fp_oses);
-               if ((entry = pool_get(&pf_osfp_entry_pl,
-                   PR_WAITOK|PR_LIMITFAIL)) == NULL) {
-                       pool_put(&pf_osfp_pl, fp);
-                       return (ENOMEM);
-               }
                pf_osfp_insert(&pf_osfp_list, fp);
        }
        memcpy(entry, &fpioc->fp_os, sizeof(*entry));
@@ -396,12 +406,18 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
        entry->fp_subtype_nm[sizeof(entry->fp_subtype_nm)-1] = '\0';
 
        SLIST_INSERT_HEAD(&fp->fp_oses, entry, fp_entry);
+       PF_UNLOCK();
+       NET_UNLOCK();
 
 #ifdef PFDEBUG
        if ((fp = pf_osfp_validate()))
                DPFPRINTF(LOG_NOTICE,
                    "Invalid fingerprint list");
 #endif /* PFDEBUG */
+
+       if (fp_prealloc != NULL)
+               pool_put(&pf_osfp_pl, fp_prealloc);
+
        return (0);
 }
 
@@ -528,6 +544,8 @@ pf_osfp_get(struct pf_osfp_ioctl *fpioc)
 
 
        memset(fpioc, 0, sizeof(*fpioc));
+       NET_LOCK();
+       PF_LOCK();
        SLIST_FOREACH(fp, &pf_osfp_list, fp_next) {
                SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
                        if (i++ == num) {
@@ -540,10 +558,14 @@ pf_osfp_get(struct pf_osfp_ioctl *fpioc)
                                fpioc->fp_getnum = num;
                                memcpy(&fpioc->fp_os, entry,
                                    sizeof(fpioc->fp_os));
+                               PF_UNLOCK();
+                               NET_UNLOCK();
                                return (0);
                        }
                }
        }
+       PF_UNLOCK();
+       NET_UNLOCK();
 
        return (EBUSY);
 }

Reply via email to