diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2017-10-16 08:22:26 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2017-10-16 08:22:26 +0000 |
commit | 953fade1239ddddd9e112d513bee0ab49319a407 (patch) | |
tree | 8734f3986ae847770d0b718e126d7038cc9a05b6 | |
parent | 5794709eb5f9f22e86feb590d86544f0bb48897e (diff) |
Last changes before running IPsec w/o KERNEL_LOCK().
Put more NET_ASSERT_LOCK() and document which globals it protects.
Add a mutex for pfkeyv2 globals.
Convert ipsp_delete_acquire() to timeout_set_proc().
Tested by Hrvoje Popovski, ok bluhm@ visa@
-rw-r--r-- | sys/net/if_enc.c | 4 | ||||
-rw-r--r-- | sys/net/pfkeyv2.c | 49 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.c | 29 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_spd.c | 38 |
5 files changed, 93 insertions, 30 deletions
diff --git a/sys/net/if_enc.c b/sys/net/if_enc.c index 35454fce639..499e8609519 100644 --- a/sys/net/if_enc.c +++ b/sys/net/if_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_enc.c,v 1.69 2017/08/11 21:24:19 mpi Exp $ */ +/* $OpenBSD: if_enc.c,v 1.70 2017/10/16 08:22:25 mpi Exp $ */ /* * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net> @@ -214,6 +214,8 @@ enc_getif(u_int id, u_int unit) { struct ifnet *ifp; + NET_ASSERT_LOCKED(); + /* Check if the caller wants to get a non-default enc interface */ if (unit > 0) { if (unit > enc_max_unit) diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c index 76a38551e17..4edfd3df3a9 100644 --- a/sys/net/pfkeyv2.c +++ b/sys/net/pfkeyv2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkeyv2.c,v 1.167 2017/10/09 08:35:38 mpi Exp $ */ +/* $OpenBSD: pfkeyv2.c,v 1.168 2017/10/16 08:22:25 mpi Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 @@ -80,6 +80,8 @@ #include <sys/kernel.h> #include <sys/proc.h> #include <sys/pool.h> +#include <sys/mutex.h> + #include <net/route.h> #include <netinet/ip_ipsp.h> #include <net/pfkeyv2.h> @@ -148,6 +150,8 @@ struct dump_state { /* Static globals */ static LIST_HEAD(, keycb) pfkeyv2_sockets = LIST_HEAD_INITIALIZER(keycb); + +struct mutex pfkeyv2_mtx = MUTEX_INITIALIZER(IPL_NONE); static uint32_t pfkeyv2_seq = 1; static int nregistered = 0; static int npromisc = 0; @@ -260,11 +264,16 @@ pfkeyv2_detach(struct socket *so, struct proc *p) LIST_REMOVE(kp, kcb_list); - if (kp->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) - nregistered--; + if (kp->flags & + (PFKEYV2_SOCKETFLAGS_REGISTERED|PFKEYV2_SOCKETFLAGS_PROMISC)) { + mtx_enter(&pfkeyv2_mtx); + if (kp->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) + nregistered--; - if (kp->flags & PFKEYV2_SOCKETFLAGS_PROMISC) - npromisc--; + if (kp->flags & PFKEYV2_SOCKETFLAGS_PROMISC) + npromisc--; + mtx_leave(&pfkeyv2_mtx); + } raw_detach(&kp->rcb); return (0); @@ -940,23 +949,22 @@ pfkeyv2_send(struct socket *so, void *message, int len) struct ipsec_acquire *ipa; struct radix_node_head *rnh; struct radix_node *rn = NULL; - struct keycb *kp, *bkp; - void *freeme = NULL, *bckptr = NULL; void *headers[SADB_EXT_MAX + 1]; - union sockaddr_union *sunionp; - struct tdb *sa1 = NULL, *sa2 = NULL; - struct sadb_msg *smsg; struct sadb_spirange *sprng; struct sadb_sa *ssa; struct sadb_supported *ssup; struct sadb_ident *sid, *did; - u_int rdomain; + int promisc; + + mtx_enter(&pfkeyv2_mtx); + promisc = npromisc; + mtx_leave(&pfkeyv2_mtx); NET_LOCK(); @@ -972,7 +980,7 @@ pfkeyv2_send(struct socket *so, void *message, int len) rdomain = kp->rdomain; /* If we have any promiscuous listeners, send them a copy of the message */ - if (npromisc) { + if (promisc) { struct mbuf *packet; if (!(freeme = malloc(sizeof(struct sadb_msg) + len, M_PFKEY, @@ -1392,7 +1400,9 @@ pfkeyv2_send(struct socket *so, void *message, int len) case SADB_REGISTER: if (!(kp->flags & PFKEYV2_SOCKETFLAGS_REGISTERED)) { kp->flags |= PFKEYV2_SOCKETFLAGS_REGISTERED; + mtx_enter(&pfkeyv2_mtx); nregistered++; + mtx_leave(&pfkeyv2_mtx); } i = sizeof(struct sadb_supported) + sizeof(ealgs); @@ -1788,11 +1798,15 @@ pfkeyv2_send(struct socket *so, void *message, int len) if (j) { kp->flags |= PFKEYV2_SOCKETFLAGS_PROMISC; + mtx_enter(&pfkeyv2_mtx); npromisc++; + mtx_leave(&pfkeyv2_mtx); } else { kp->flags &= ~PFKEYV2_SOCKETFLAGS_PROMISC; + mtx_enter(&pfkeyv2_mtx); npromisc--; + mtx_leave(&pfkeyv2_mtx); } } } @@ -1859,11 +1873,15 @@ pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw, struct sadb_prop *sa_prop; struct sadb_msg *smsg; int rval = 0; - int i, j; + int i, j, registered; + mtx_enter(&pfkeyv2_mtx); *seq = pfkeyv2_seq++; - if (!nregistered) { + registered = nregistered; + mtx_leave(&pfkeyv2_mtx); + + if (!registered) { rval = ESRCH; goto ret; } @@ -2100,7 +2118,10 @@ pfkeyv2_expire(struct tdb *sa, u_int16_t type) smsg->sadb_msg_type = SADB_EXPIRE; smsg->sadb_msg_satype = sa->tdb_satype; smsg->sadb_msg_len = i / sizeof(uint64_t); + + mtx_enter(&pfkeyv2_mtx); smsg->sadb_msg_seq = pfkeyv2_seq++; + mtx_leave(&pfkeyv2_mtx); headers[SADB_EXT_SA] = p; export_sa(&p, sa); diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c index 0dc50de6219..6fa11ee087d 100644 --- a/sys/netinet/ip_ipsp.c +++ b/sys/netinet/ip_ipsp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.c,v 1.227 2017/10/11 13:44:49 mpi Exp $ */ +/* $OpenBSD: ip_ipsp.c,v 1.228 2017/10/16 08:22:25 mpi Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), @@ -87,16 +87,14 @@ int tdb_hash(u_int, u_int32_t, union sockaddr_union *, u_int8_t); int ipsec_in_use = 0; u_int64_t ipsec_last_added = 0; +int ipsec_ids_idle = 100; /* keep free ids for 100s */ -struct ipsec_policy_head ipsec_policy_head = - TAILQ_HEAD_INITIALIZER(ipsec_policy_head); -struct ipsec_acquire_head ipsec_acquire_head = - TAILQ_HEAD_INITIALIZER(ipsec_acquire_head); - +/* Protected by the NET_LOCK(). */ u_int32_t ipsec_ids_next_flow = 1; /* may not be zero */ -int ipsec_ids_idle = 100; /* keep free ids for 100s */ struct ipsec_ids_tree ipsec_ids_tree; struct ipsec_ids_flows ipsec_ids_flows; +struct ipsec_policy_head ipsec_policy_head = + TAILQ_HEAD_INITIALIZER(ipsec_policy_head); void ipsp_ids_timeout(void *); static inline int ipsp_ids_cmp(const struct ipsec_ids *, @@ -173,6 +171,7 @@ struct xformsw *xformswNXFORMSW = &xformsw[nitems(xformsw)]; #define TDB_HASHSIZE_INIT 32 +/* Protected by the NET_LOCK(). */ static SIPHASH_KEY tdbkey; static struct tdb **tdbh = NULL; static struct tdb **tdbdst = NULL; @@ -190,6 +189,8 @@ tdb_hash(u_int rdomain, u_int32_t spi, union sockaddr_union *dst, { SIPHASH_CTX ctx; + NET_ASSERT_LOCKED(); + SipHash24_Init(&ctx, &tdbkey); SipHash24_Update(&ctx, &rdomain, sizeof(rdomain)); SipHash24_Update(&ctx, &spi, sizeof(spi)); @@ -336,6 +337,8 @@ gettdbbysrcdst(u_int rdomain, u_int32_t spi, union sockaddr_union *src, struct tdb *tdbp; union sockaddr_union su_null; + NET_ASSERT_LOCKED(); + if (tdbsrc == NULL) return (struct tdb *) NULL; @@ -420,6 +423,8 @@ gettdbbydst(u_int rdomain, union sockaddr_union *dst, u_int8_t sproto, u_int32_t hashval; struct tdb *tdbp; + NET_ASSERT_LOCKED(); + if (tdbdst == NULL) return (struct tdb *) NULL; @@ -451,6 +456,8 @@ gettdbbysrc(u_int rdomain, union sockaddr_union *src, u_int8_t sproto, u_int32_t hashval; struct tdb *tdbp; + NET_ASSERT_LOCKED(); + if (tdbsrc == NULL) return (struct tdb *) NULL; @@ -788,6 +795,8 @@ tdb_alloc(u_int rdomain) { struct tdb *tdbp; + NET_ASSERT_LOCKED(); + tdbp = malloc(sizeof(*tdbp), M_TDB, M_WAITOK | M_ZERO); TAILQ_INIT(&tdbp->tdb_policy_head); @@ -812,6 +821,8 @@ tdb_free(struct tdb *tdbp) { struct ipsec_policy *ipo; + NET_ASSERT_LOCKED(); + if (tdbp->tdb_xform) { (*(tdbp->tdb_xform->xf_zeroize))(tdbp); tdbp->tdb_xform = NULL; @@ -944,6 +955,8 @@ ipsp_ids_insert(struct ipsec_ids *ids) struct ipsec_ids *found; u_int32_t start_flow; + NET_ASSERT_LOCKED(); + found = RBT_INSERT(ipsec_ids_tree, &ipsec_ids_tree, ids); if (found) { /* if refcount was zero, then timeout is running */ @@ -977,6 +990,8 @@ ipsp_ids_lookup(u_int32_t ipsecflowinfo) { struct ipsec_ids key; + NET_ASSERT_LOCKED(); + key.id_flow = ipsecflowinfo; return RBT_FIND(ipsec_ids_flows, &ipsec_ids_flows, &key); } diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h index df145de2b64..cd6d58e9d8f 100644 --- a/sys/netinet/ip_ipsp.h +++ b/sys/netinet/ip_ipsp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.h,v 1.183 2017/06/26 09:08:00 patrick Exp $ */ +/* $OpenBSD: ip_ipsp.h,v 1.184 2017/10/16 08:22:25 mpi Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), @@ -440,7 +440,6 @@ extern struct auth_hash auth_hash_hmac_ripemd_160_96; extern struct comp_algo comp_algo_deflate; extern TAILQ_HEAD(ipsec_policy_head, ipsec_policy) ipsec_policy_head; -extern TAILQ_HEAD(ipsec_acquire_head, ipsec_acquire) ipsec_acquire_head; /* Misc. */ #ifdef ENCDEBUG diff --git a/sys/netinet/ip_spd.c b/sys/netinet/ip_spd.c index 5d8b3a7b19e..8a26e990b6c 100644 --- a/sys/netinet/ip_spd.c +++ b/sys/netinet/ip_spd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_spd.c,v 1.92 2017/04/06 14:25:18 dhill Exp $ */ +/* $OpenBSD: ip_spd.c,v 1.93 2017/10/16 08:22:25 mpi Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * @@ -45,7 +45,8 @@ int ipsp_acquire_sa(struct ipsec_policy *, union sockaddr_union *, union sockaddr_union *, struct sockaddr_encap *, struct mbuf *); struct ipsec_acquire *ipsp_pending_acquire(struct ipsec_policy *, union sockaddr_union *); -void ipsp_delete_acquire(void *); +void ipsp_delete_acquire_timo(void *); +void ipsp_delete_acquire(struct ipsec_acquire *); #ifdef ENCDEBUG #define DPRINTF(x) if (encdebug) printf x @@ -56,16 +57,21 @@ void ipsp_delete_acquire(void *); struct pool ipsec_policy_pool; struct pool ipsec_acquire_pool; int ipsec_policy_pool_initialized = 0; -int ipsec_acquire_pool_initialized = 0; +/* Protected by the NET_LOCK(). */ +int ipsec_acquire_pool_initialized = 0; struct radix_node_head **spd_tables; unsigned int spd_table_max; +TAILQ_HEAD(ipsec_acquire_head, ipsec_acquire) ipsec_acquire_head = + TAILQ_HEAD_INITIALIZER(ipsec_acquire_head); struct radix_node_head * spd_table_get(unsigned int rtableid) { unsigned int rdomain; + NET_ASSERT_LOCKED(); + if (spd_tables == NULL) return (NULL); @@ -83,6 +89,8 @@ spd_table_add(unsigned int rtableid) unsigned int rdomain; void *p; + NET_ASSERT_LOCKED(); + rdomain = rtable_l2(rtableid); if (spd_tables == NULL || rdomain > spd_table_max) { if ((p = mallocarray(rdomain + 1, sizeof(*rnh), @@ -135,6 +143,8 @@ ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction, int signore = 0, dignore = 0; u_int rdomain = rtable_l2(m->m_pkthdr.ph_rtableid); + NET_ASSERT_LOCKED(); + /* * If there are no flows in place, there's no point * continuing with the SPD lookup. @@ -587,6 +597,8 @@ ipsec_delete_policy(struct ipsec_policy *ipo) struct radix_node *rn = (struct radix_node *)ipo; int err = 0; + NET_ASSERT_LOCKED(); + if (--ipo->ipo_ref_count > 0) return 0; @@ -614,13 +626,23 @@ ipsec_delete_policy(struct ipsec_policy *ipo) return err; } +void +ipsp_delete_acquire_timo(void *v) +{ + struct ipsec_acquire *ipa = v; + + NET_LOCK(); + ipsp_delete_acquire(ipa); + NET_UNLOCK(); +} + /* * Delete a pending IPsec acquire record. */ void -ipsp_delete_acquire(void *v) +ipsp_delete_acquire(struct ipsec_acquire *ipa) { - struct ipsec_acquire *ipa = v; + NET_ASSERT_LOCKED(); timeout_del(&ipa->ipa_timeout); TAILQ_REMOVE(&ipsec_acquire_head, ipa, ipa_next); @@ -639,6 +661,8 @@ ipsp_pending_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw) { struct ipsec_acquire *ipa; + NET_ASSERT_LOCKED(); + TAILQ_FOREACH (ipa, &ipo->ipo_acquires, ipa_ipo_next) { if (!memcmp(gw, &ipa->ipa_addr, gw->sa.sa_len)) return ipa; @@ -657,6 +681,8 @@ ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw, { struct ipsec_acquire *ipa; + NET_ASSERT_LOCKED(); + /* Check whether request has been made already. */ if ((ipa = ipsp_pending_acquire(ipo, gw)) != NULL) return 0; @@ -674,7 +700,7 @@ ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw, ipa->ipa_addr = *gw; - timeout_set(&ipa->ipa_timeout, ipsp_delete_acquire, ipa); + timeout_set_proc(&ipa->ipa_timeout, ipsp_delete_acquire_timo, ipa); ipa->ipa_info.sen_len = ipa->ipa_mask.sen_len = SENT_LEN; ipa->ipa_info.sen_family = ipa->ipa_mask.sen_family = PF_KEY; |