On Wed, Oct 11, 2017 at 05:01:46PM +0200, Martin Pieuchot wrote: > Tests and comments welcome.
All regress tests passed. Code looks reasonable. OK bluhm@ > Index: net/if_enc.c > =================================================================== > RCS file: /cvs/src/sys/net/if_enc.c,v > retrieving revision 1.69 > diff -u -p -r1.69 if_enc.c > --- net/if_enc.c 11 Aug 2017 21:24:19 -0000 1.69 > +++ net/if_enc.c 11 Oct 2017 14:44:48 -0000 > @@ -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) > Index: net/pfkeyv2.c > =================================================================== > RCS file: /cvs/src/sys/net/pfkeyv2.c,v > retrieving revision 1.167 > diff -u -p -r1.167 pfkeyv2.c > --- net/pfkeyv2.c 9 Oct 2017 08:35:38 -0000 1.167 > +++ net/pfkeyv2.c 11 Oct 2017 14:44:49 -0000 > @@ -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 > > LIST_REMOVE(kp, kcb_list); > > - if (kp->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) > - nregistered--; > - > - if (kp->flags & PFKEYV2_SOCKETFLAGS_PROMISC) > - npromisc--; > + 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--; > + mtx_leave(&pfkeyv2_mtx); > + } > > raw_detach(&kp->rcb); > return (0); > @@ -940,23 +949,22 @@ pfkeyv2_send(struct socket *so, void *me > 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 *me > 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 *me > 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 *me > 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 > 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 > 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); > Index: netinet/ip_ipsp.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_ipsp.c,v > retrieving revision 1.227 > diff -u -p -r1.227 ip_ipsp.c > --- netinet/ip_ipsp.c 11 Oct 2017 13:44:49 -0000 1.227 > +++ netinet/ip_ipsp.c 11 Oct 2017 14:44:50 -0000 > @@ -87,16 +87,14 @@ int tdb_hash(u_int, u_int32_t, union so > > 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 = &xform > > #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, u > { > 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 > 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 sockadd > 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 sockadd > 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 */ > @@ -976,6 +989,8 @@ struct ipsec_ids * > 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); > Index: netinet/ip_ipsp.h > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_ipsp.h,v > retrieving revision 1.183 > diff -u -p -r1.183 ip_ipsp.h > --- netinet/ip_ipsp.h 26 Jun 2017 09:08:00 -0000 1.183 > +++ netinet/ip_ipsp.h 11 Oct 2017 14:44:51 -0000 > @@ -440,7 +440,6 @@ extern struct auth_hash auth_hash_hmac_r > 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 > Index: netinet/ip_spd.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_spd.c,v > retrieving revision 1.92 > diff -u -p -r1.92 ip_spd.c > --- netinet/ip_spd.c 6 Apr 2017 14:25:18 -0000 1.92 > +++ netinet/ip_spd.c 11 Oct 2017 14:44:51 -0000 > @@ -45,7 +45,8 @@ int ipsp_acquire_sa(struct ipsec_policy > 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 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 > 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 > 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 > { > 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 > { > 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 > > 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;