Hello,
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.
OK?
thanks and
regards
sashan
--------8<---------------8<---------------8<------------------8<--------
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();
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;
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);
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);
}