On Fri, Oct 16, 2020 at 11:37:22AM +0200, Alexandr Nedvedicky wrote:
> I've just found a forgotten diff in my tree. The diff pushes the NET_LCOK()
> further down in PF driver ioctl() path. The idea is to avoid sleeping while
> holding a NET_LOCK(). this typically may happen when we need to allocate
> memory. The diff is the first step as it takes care of easy/straightforward
> cases of such allocations. The allocations, which still may happen under
> the NET_LOCK() require more work in areas:
> PF tables,
> packet queues,
> transactions,
>
> 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.
> diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
> index ef7d995e5a7..bac644fa6d1 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();
As an example, this is the first pf_rm_rule() invocation in your diff
(or its context) which continues to be under PF/NET_LOCK().
> break;
> }
> rule->cuid = p->p_ucred->cr_ruid;
> @@ -1219,10 +1247,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int
> flags, struct proc *p)
> break;
> #endif /* INET6 */
> default:
> - pf_rm_rule(NULL, rule);
> - rule = NULL;
> error = EAFNOSUPPORT;
> PF_UNLOCK();
> + NET_UNLOCK();
> + pf_rm_rule(NULL, rule);
> + rule = NULL;
Here's the second one, but you move that pf_rm_rule() call out of the
lock.
> goto fail;
> }
> tail = TAILQ_LAST(ruleset->rules.inactive.ptr,
> @@ -1256,8 +1285,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags,
> struct proc *p)
> error = EINVAL;
>
> if (error) {
> - pf_rm_rule(NULL, rule);
> PF_UNLOCK();
> + NET_UNLOCK();
> + pf_rm_rule(NULL, rule);
Same here.
> 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);
> }
>