diff options
author | Alexandr Nedvedicky <sashan@cvs.openbsd.org> | 2017-10-30 22:35:51 +0000 |
---|---|---|
committer | Alexandr Nedvedicky <sashan@cvs.openbsd.org> | 2017-10-30 22:35:51 +0000 |
commit | 6c5e67580e475745e06b9219a0397210ebc416ea (patch) | |
tree | c3ab2486901e588fc8e3e2e120623a782f6f7852 /sys/net | |
parent | e41b4bdf538359dd784d5aa5f71d78897a65e352 (diff) |
- fine tuning PF_LOCK in pfioctl()
(extra thanks to Hrvoje for testing)
OK mpi@
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/pf_ioctl.c | 179 |
1 files changed, 176 insertions, 3 deletions
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c index de40e934112..f6ad2cb8c53 100644 --- a/sys/net/pf_ioctl.c +++ b/sys/net/pf_ioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_ioctl.c,v 1.322 2017/08/11 21:24:19 mpi Exp $ */ +/* $OpenBSD: pf_ioctl.c,v 1.323 2017/10/30 22:35:50 sashan Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1003,10 +1003,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } NET_LOCK(); - PF_LOCK(); switch (cmd) { case DIOCSTART: + PF_LOCK(); if (pf_status.running) error = EEXIST; else { @@ -1020,9 +1020,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pf_create_queues(); DPFPRINTF(LOG_NOTICE, "pf: started"); } + PF_UNLOCK(); break; case DIOCSTOP: + PF_LOCK(); if (!pf_status.running) error = ENOENT; else { @@ -1031,6 +1033,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pf_remove_queues(); DPFPRINTF(LOG_NOTICE, "pf: stopped"); } + PF_UNLOCK(); break; case DIOCGETQUEUES: { @@ -1038,6 +1041,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; + PF_LOCK(); pq->ticket = pf_main_ruleset.rules.active.ticket; /* save state to not run over them all each time? */ @@ -1047,6 +1051,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) nr++; } pq->nr = nr; + PF_UNLOCK(); break; } @@ -1055,8 +1060,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pf_queuespec *qs; u_int32_t nr = 0; + PF_LOCK(); if (pq->ticket != pf_main_ruleset.rules.active.ticket) { error = EBUSY; + PF_UNLOCK(); break; } @@ -1066,9 +1073,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) qs = TAILQ_NEXT(qs, entries); if (qs == NULL) { error = EBUSY; + PF_UNLOCK(); break; } bcopy(qs, &pq->queue, sizeof(pq->queue)); + PF_UNLOCK(); break; } @@ -1078,8 +1087,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) u_int32_t nr; int nbytes; + PF_LOCK(); if (pq->ticket != pf_main_ruleset.rules.active.ticket) { error = EBUSY; + PF_UNLOCK(); break; } nbytes = pq->nbytes; @@ -1091,6 +1102,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) qs = TAILQ_NEXT(qs, entries); if (qs == NULL) { error = EBUSY; + PF_UNLOCK(); break; } bcopy(qs, &pq->queue, sizeof(pq->queue)); @@ -1104,6 +1116,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) &nbytes); if (error == 0) pq->nbytes = nbytes; + PF_UNLOCK(); break; } @@ -1111,13 +1124,16 @@ 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; + PF_UNLOCK(); break; } bcopy(&q->queue, qs, sizeof(*qs)); @@ -1126,18 +1142,21 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pf_qname2qid(qs->parent, 0)) == 0) { pool_put(&pf_queue_pl, qs); error = ESRCH; + PF_UNLOCK(); break; } qs->kif = pfi_kif_get(qs->ifname); if (qs->kif == NULL) { pool_put(&pf_queue_pl, qs); error = ESRCH; + PF_UNLOCK(); break; } /* XXX resolve bw percentage specs */ pfi_kif_ref(qs->kif, PFI_KIF_REF_RULE); TAILQ_INSERT_TAIL(pf_queues_inactive, qs, entries); + PF_UNLOCK(); break; } @@ -1147,28 +1166,34 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pf_ruleset *ruleset; struct pf_rule *rule, *tail; + PF_LOCK(); pr->anchor[sizeof(pr->anchor) - 1] = 0; ruleset = pf_find_ruleset(pr->anchor); if (ruleset == NULL) { error = EINVAL; + PF_UNLOCK(); break; } if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { error = EINVAL; + PF_UNLOCK(); 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(); break; } if ((error = pf_rule_copyin(&pr->rule, rule, ruleset))) { pf_rm_rule(NULL, rule); rule = NULL; + PF_UNLOCK(); break; } rule->cuid = p->p_ucred->cr_ruid; @@ -1187,6 +1212,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pf_rm_rule(NULL, rule); rule = NULL; error = EAFNOSUPPORT; + PF_UNLOCK(); goto fail; } tail = TAILQ_LAST(ruleset->rules.inactive.ptr, @@ -1221,12 +1247,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) if (error) { pf_rm_rule(NULL, rule); + PF_UNLOCK(); break; } TAILQ_INSERT_TAIL(ruleset->rules.inactive.ptr, rule, entries); rule->ruleset = ruleset; ruleset->rules.inactive.rcount++; + PF_UNLOCK(); break; } @@ -1235,10 +1263,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pf_ruleset *ruleset; struct pf_rule *tail; + PF_LOCK(); pr->anchor[sizeof(pr->anchor) - 1] = 0; ruleset = pf_find_ruleset(pr->anchor); if (ruleset == NULL) { error = EINVAL; + PF_UNLOCK(); break; } tail = TAILQ_LAST(ruleset->rules.active.ptr, pf_rulequeue); @@ -1247,6 +1277,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) else pr->nr = 0; pr->ticket = ruleset->rules.active.ticket; + PF_UNLOCK(); break; } @@ -1256,14 +1287,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pf_rule *rule; int i; + PF_LOCK(); pr->anchor[sizeof(pr->anchor) - 1] = 0; ruleset = pf_find_ruleset(pr->anchor); if (ruleset == NULL) { error = EINVAL; + PF_UNLOCK(); break; } if (pr->ticket != ruleset->rules.active.ticket) { error = EBUSY; + PF_UNLOCK(); break; } rule = TAILQ_FIRST(ruleset->rules.active.ptr); @@ -1271,6 +1305,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) rule = TAILQ_NEXT(rule, entries); if (rule == NULL) { error = EBUSY; + PF_UNLOCK(); break; } bcopy(rule, &pr->rule, sizeof(struct pf_rule)); @@ -1286,6 +1321,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pr->rule.ruleset = NULL; if (pf_anchor_copyout(ruleset, rule, pr)) { error = EBUSY; + PF_UNLOCK(); break; } pf_addr_copyout(&pr->rule.src.addr); @@ -1306,6 +1342,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) rule->bytes[0] = rule->bytes[1] = 0; rule->states_tot = 0; } + PF_UNLOCK(); break; } @@ -1320,23 +1357,28 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = EINVAL; break; } + PF_LOCK(); ruleset = pf_find_ruleset(pcr->anchor); if (ruleset == NULL) { error = EINVAL; + PF_UNLOCK(); break; } if (pcr->action == PF_CHANGE_GET_TICKET) { pcr->ticket = ++ruleset->rules.active.ticket; + PF_UNLOCK(); break; } else { if (pcr->ticket != ruleset->rules.active.ticket) { error = EINVAL; + PF_UNLOCK(); break; } if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { error = EINVAL; + PF_UNLOCK(); break; } } @@ -1346,6 +1388,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) PR_WAITOK|PR_LIMITFAIL|PR_ZERO); if (newrule == NULL) { error = ENOMEM; + PF_UNLOCK(); break; } pf_rule_copyin(&pcr->rule, newrule, ruleset); @@ -1364,6 +1407,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) default: pool_put(&pf_rule_pl, newrule); error = EAFNOSUPPORT; + PF_UNLOCK(); goto fail; } @@ -1384,6 +1428,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(); break; } } @@ -1401,6 +1446,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) if (newrule != NULL) pf_rm_rule(NULL, newrule); error = EINVAL; + PF_UNLOCK(); break; } } @@ -1432,6 +1478,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pf_calc_skip_steps(ruleset->rules.active.ptr); pf_remove_if_empty_ruleset(ruleset); + PF_UNLOCK(); break; } @@ -1440,6 +1487,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; + PF_LOCK(); for (s = RB_MIN(pf_state_tree_id, &tree_id); s; s = nexts) { nexts = RB_NEXT(pf_state_tree_id, &tree_id, s); @@ -1457,6 +1505,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) #if NPFSYNC > 0 pfsync_clear_states(pf_status.hostid, psk->psk_ifname); #endif /* NPFSYNC > 0 */ + PF_UNLOCK(); break; } @@ -1474,10 +1523,12 @@ 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; + PF_LOCK(); if ((s = pf_find_state_byid(&psk->psk_pfcmp))) { pf_remove_state(s); psk->psk_killed = 1; } + PF_UNLOCK(); break; } @@ -1489,6 +1540,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; + PF_LOCK(); for (i = 0; i < nitems(dirs); i++) { if (dirs[i] == PF_IN) { sidx = 0; @@ -1529,9 +1581,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } if (killed) psk->psk_killed = killed; + PF_UNLOCK(); break; } + PF_LOCK(); for (s = RB_MIN(pf_state_tree_id, &tree_id); s; s = nexts) { nexts = RB_NEXT(pf_state_tree_id, &tree_id, s); @@ -1577,6 +1631,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } } psk->psk_killed = killed; + PF_UNLOCK(); break; } @@ -1589,7 +1644,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = EINVAL; break; } + PF_LOCK(); error = pfsync_state_import(sp, PFSYNC_SI_IOCTL); + PF_UNLOCK(); break; } #endif /* NPFSYNC > 0 */ @@ -1603,13 +1660,16 @@ 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; + PF_LOCK(); s = pf_find_state_byid(&id_key); if (s == NULL) { error = ENOENT; + PF_UNLOCK(); break; } pf_state_export(&ps->state, s); + PF_UNLOCK(); break; } @@ -1629,6 +1689,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) p = ps->ps_states; + PF_LOCK(); state = TAILQ_FIRST(&state_list); while (state) { if (state->timeout != PFTM_UNLINKED) { @@ -1645,6 +1706,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } state = TAILQ_NEXT(state, entry_list); } + PF_UNLOCK(); ps->ps_len = sizeof(struct pfsync_state) * nr; @@ -1654,29 +1716,36 @@ 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; + PF_LOCK(); bcopy(&pf_status, s, sizeof(struct pf_status)); pfi_update_status(s->ifname, s); + PF_UNLOCK(); break; } case DIOCSETSTATUSIF: { struct pfioc_iface *pi = (struct pfioc_iface *)addr; + PF_LOCK(); if (pi->pfiio_name[0] == 0) { bzero(pf_status.ifname, IFNAMSIZ); + PF_UNLOCK(); break; } strlcpy(pf_trans_set.statusif, pi->pfiio_name, IFNAMSIZ); pf_trans_set.mask |= PF_TSET_STATUSIF; + PF_UNLOCK(); break; } case DIOCCLRSTATUS: { struct pfioc_iface *pi = (struct pfioc_iface *)addr; + PF_LOCK(); /* if ifname is specified, clear counters there only */ if (pi->pfiio_name[0]) { pfi_update_status(pi->pfiio_name, NULL); + PF_UNLOCK(); break; } @@ -1685,6 +1754,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) bzero(pf_status.scounters, sizeof(pf_status.scounters)); pf_status.since = time_uptime; + PF_UNLOCK(); break; } @@ -1717,6 +1787,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) PF_ACPY(&key.addr[didx], &pnl->daddr, pnl->af); key.port[didx] = pnl->dport; + PF_LOCK(); state = pf_find_state_all(&key, direction, &m); if (m > 1) @@ -1730,6 +1801,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pnl->rrdomain = sk->rdomain; } else error = ENOENT; + PF_UNLOCK(); } break; } @@ -1742,10 +1814,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = EINVAL; goto fail; } + 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(); break; } @@ -1756,7 +1830,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = EINVAL; goto fail; } + PF_LOCK(); pt->seconds = pf_default_rule.timeout[pt->timeout]; + PF_UNLOCK(); break; } @@ -1767,39 +1843,48 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = EINVAL; goto fail; } + PF_LOCK(); pl->limit = pf_pool_limits[pl->index].limit; + PF_UNLOCK(); break; } case DIOCSETLIMIT: { struct pfioc_limit *pl = (struct pfioc_limit *)addr; + PF_LOCK(); if (pl->index < 0 || pl->index >= PF_LIMIT_MAX || pf_pool_limits[pl->index].pp == NULL) { error = EINVAL; + PF_UNLOCK(); goto fail; } if (((struct pool *)pf_pool_limits[pl->index].pp)->pr_nout > pl->limit) { error = EBUSY; + PF_UNLOCK(); goto fail; } /* Fragments reference mbuf clusters. */ if (pl->index == PF_LIMIT_FRAGS && pl->limit > nmbclust) { error = EINVAL; + PF_UNLOCK(); goto fail; } pf_pool_limits[pl->index].limit_new = pl->limit; pl->limit = pf_pool_limits[pl->index].limit; + PF_UNLOCK(); break; } case DIOCSETDEBUG: { u_int32_t *level = (u_int32_t *)addr; + PF_LOCK(); pf_trans_set.debug = *level; pf_trans_set.mask |= PF_TSET_DEBUG; + PF_UNLOCK(); break; } @@ -1808,9 +1893,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pf_ruleset *ruleset; struct pf_anchor *anchor; + PF_LOCK(); pr->path[sizeof(pr->path) - 1] = 0; if ((ruleset = pf_find_ruleset(pr->path)) == NULL) { error = EINVAL; + PF_UNLOCK(); break; } pr->nr = 0; @@ -1824,6 +1911,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) &ruleset->anchor->children) pr->nr++; } + PF_UNLOCK(); break; } @@ -1833,9 +1921,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pf_anchor *anchor; u_int32_t nr = 0; + PF_LOCK(); pr->path[sizeof(pr->path) - 1] = 0; if ((ruleset = pf_find_ruleset(pr->path)) == NULL) { error = EINVAL; + PF_UNLOCK(); break; } pr->name[0] = 0; @@ -1845,6 +1935,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) if (anchor->parent == NULL && nr++ == pr->nr) { strlcpy(pr->name, anchor->name, sizeof(pr->name)); + PF_UNLOCK(); break; } } else { @@ -1853,11 +1944,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) if (nr++ == pr->nr) { strlcpy(pr->name, anchor->name, sizeof(pr->name)); + PF_UNLOCK(); break; } } if (!pr->name[0]) error = EBUSY; + PF_UNLOCK(); break; } @@ -1868,8 +1961,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + PF_LOCK(); error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); + PF_UNLOCK(); break; } @@ -1880,8 +1975,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + PF_LOCK(); error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL); + PF_UNLOCK(); break; } @@ -1892,8 +1989,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + PF_LOCK(); error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); + PF_UNLOCK(); break; } @@ -1904,8 +2003,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + PF_LOCK(); error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); + PF_UNLOCK(); break; } @@ -1916,8 +2017,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + PF_LOCK(); error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); + PF_UNLOCK(); break; } @@ -1928,8 +2031,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + PF_LOCK(); error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL); + PF_UNLOCK(); break; } @@ -1940,9 +2045,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + 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(); break; } @@ -1953,8 +2060,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + PF_LOCK(); error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); + PF_UNLOCK(); break; } @@ -1965,9 +2074,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + 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(); break; } @@ -1978,9 +2089,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + 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(); break; } @@ -1991,10 +2104,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + 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(); break; } @@ -2005,8 +2120,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + PF_LOCK(); error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); + PF_UNLOCK(); break; } @@ -2017,8 +2134,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + PF_LOCK(); error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); + PF_UNLOCK(); break; } @@ -2029,9 +2148,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + 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(); break; } @@ -2042,9 +2163,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + 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(); break; } @@ -2055,21 +2178,27 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + 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(); 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; } @@ -2083,6 +2212,7 @@ 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); pf_default_rule_new = pf_default_rule; @@ -2092,6 +2222,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 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)) == @@ -2099,6 +2230,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); error = ENAMETOOLONG; + PF_UNLOCK(); goto fail; } switch (ioe->type) { @@ -2110,6 +2242,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) &ioe->ticket, NULL, 0))) { free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); + PF_UNLOCK(); goto fail; } break; @@ -2118,6 +2251,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) ioe->anchor))) { free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); + PF_UNLOCK(); goto fail; } break; @@ -2126,11 +2260,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); error = EFAULT; + PF_UNLOCK(); goto fail; } } free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); + PF_UNLOCK(); break; } @@ -2144,6 +2280,7 @@ 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); for (i = 0; i < io->size; i++) { @@ -2151,6 +2288,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 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)) == @@ -2158,6 +2296,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); error = ENAMETOOLONG; + PF_UNLOCK(); goto fail; } switch (ioe->type) { @@ -2169,6 +2308,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) ioe->ticket, NULL, 0))) { free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); + PF_UNLOCK(); goto fail; /* really bad */ } break; @@ -2177,6 +2317,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) ioe->anchor))) { free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); + PF_UNLOCK(); goto fail; /* really bad */ } break; @@ -2184,6 +2325,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); + PF_UNLOCK(); break; } @@ -2198,6 +2340,7 @@ 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); /* first makes sure everything will succeed */ @@ -2206,6 +2349,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 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)) == @@ -2213,6 +2357,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); error = ENAMETOOLONG; + PF_UNLOCK(); goto fail; } switch (ioe->type) { @@ -2223,6 +2368,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); error = EBUSY; + PF_UNLOCK(); goto fail; } break; @@ -2235,6 +2381,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); error = EBUSY; + PF_UNLOCK(); goto fail; } break; @@ -2251,6 +2398,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); error = EBUSY; + PF_UNLOCK(); goto fail; } } @@ -2260,6 +2408,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 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)) == @@ -2267,6 +2416,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); error = ENAMETOOLONG; + PF_UNLOCK(); goto fail; } switch (ioe->type) { @@ -2278,6 +2428,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) NULL, NULL, 0))) { free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); + PF_UNLOCK(); goto fail; /* really bad */ } break; @@ -2286,6 +2437,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) ioe->anchor))) { free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); + PF_UNLOCK(); goto fail; /* really bad */ } break; @@ -2299,6 +2451,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 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; @@ -2316,6 +2469,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pf_trans_set_commit(); free(table, M_TEMP, sizeof(*table)); free(ioe, M_TEMP, sizeof(*ioe)); + PF_UNLOCK(); break; } @@ -2325,10 +2479,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) u_int32_t nr = 0; int space = psn->psn_len; + 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(); break; } @@ -2364,6 +2520,7 @@ 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(); goto fail; } p++; @@ -2372,6 +2529,7 @@ 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(); break; } @@ -2379,11 +2537,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) struct pf_src_node *n; struct pf_state *state; + PF_LOCK(); RB_FOREACH(state, pf_state_tree_id, &tree_id) pf_src_tree_remove_state(state); RB_FOREACH(n, pf_src_tree, &tree_src_tracking) n->expire = 1; pf_purge_expired_src_nodes(1); + PF_UNLOCK(); break; } @@ -2394,6 +2554,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; + PF_LOCK(); RB_FOREACH(sn, pf_src_tree, &tree_src_tracking) { if (PF_MATCHA(psnk->psnk_src.neg, &psnk->psnk_src.addr.v.a.addr, @@ -2417,22 +2578,27 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pf_purge_expired_src_nodes(1); psnk->psnk_killed = killed; + PF_UNLOCK(); break; } case DIOCSETHOSTID: { u_int32_t *hostid = (u_int32_t *)addr; + PF_LOCK(); if (*hostid == 0) pf_trans_set.hostid = arc4random(); else pf_trans_set.hostid = *hostid; pf_trans_set.mask |= PF_TSET_HOSTID; + PF_UNLOCK(); break; } case DIOCOSFPFLUSH: + PF_LOCK(); pf_osfp_flush(); + PF_UNLOCK(); break; case DIOCIGETIFACES: { @@ -2442,30 +2608,38 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = ENODEV; break; } + PF_LOCK(); error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer, &io->pfiio_size); + PF_UNLOCK(); break; } case DIOCSETIFFLAG: { struct pfioc_iface *io = (struct pfioc_iface *)addr; + PF_LOCK(); error = pfi_set_flags(io->pfiio_name, io->pfiio_flags); + PF_UNLOCK(); break; } case DIOCCLRIFFLAG: { struct pfioc_iface *io = (struct pfioc_iface *)addr; + PF_LOCK(); error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags); + PF_UNLOCK(); break; } case DIOCSETREASS: { u_int32_t *reass = (u_int32_t *)addr; + PF_LOCK(); pf_trans_set.reass = *reass; pf_trans_set.mask |= PF_TSET_REASS; + PF_UNLOCK(); break; } @@ -2474,7 +2648,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } fail: - PF_UNLOCK(); NET_UNLOCK(); return (error); } |