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;

Reply via email to