Author: ae
Date: Wed Sep 26 14:47:51 2018
New Revision: 338945
URL: https://svnweb.freebsd.org/changeset/base/338945

Log:
  Fix witness warning in xform_init().
  
  Do not call crypto_newsession() while holding xforms_lock mutex.
  Release mutex before invoking crypto_newsession(), and use
  ipsec_kmod_enter()/ipsec_kmod_exit() functions to protect from doing
  access to unloaded kernel module memory.
  
  Move xform-releated functions into subr_ipsec.c to be able use
  ipsec_kmod_* functions. Also unconditionally build ipsec_kmod_*
  functions, since now they are always used by IPSec code.
  
  Add xf_cntr field to struct xformsw, it is used by ipsec_kmod_*
  functions. Also constify xf_name field, since it is not expected to be
  modified.
  
  Approved by:  re (kib)
  Differential Revision:        https://reviews.freebsd.org/D17302

Modified:
  head/sys/netipsec/key.c
  head/sys/netipsec/key.h
  head/sys/netipsec/subr_ipsec.c
  head/sys/netipsec/xform.h

Modified: head/sys/netipsec/key.c
==============================================================================
--- head/sys/netipsec/key.c     Wed Sep 26 14:32:36 2018        (r338944)
+++ head/sys/netipsec/key.c     Wed Sep 26 14:47:51 2018        (r338945)
@@ -534,14 +534,6 @@ MALLOC_DEFINE(M_IPSEC_SPDCACHE, "ipsec-spdcache", "ips
 VNET_DEFINE_STATIC(uma_zone_t, key_lft_zone);
 #define        V_key_lft_zone          VNET(key_lft_zone)
 
-static LIST_HEAD(xforms_list, xformsw) xforms = LIST_HEAD_INITIALIZER();
-static struct mtx xforms_lock;
-#define        XFORMS_LOCK_INIT()      \
-    mtx_init(&xforms_lock, "xforms_list", "IPsec transforms list", MTX_DEF)
-#define        XFORMS_LOCK_DESTROY()   mtx_destroy(&xforms_lock)
-#define        XFORMS_LOCK()           mtx_lock(&xforms_lock)
-#define        XFORMS_UNLOCK()         mtx_unlock(&xforms_lock)
-
 /*
  * set parameters into secpolicyindex buffer.
  * Must allocate secpolicyindex buffer passed to this function.
@@ -717,7 +709,6 @@ static int key_delete(struct socket *, struct mbuf *,
        const struct sadb_msghdr *);
 static int key_delete_all(struct socket *, struct mbuf *,
        const struct sadb_msghdr *, struct secasindex *);
-static void key_delete_xform(const struct xformsw *);
 static int key_get(struct socket *, struct mbuf *,
        const struct sadb_msghdr *);
 
@@ -750,7 +741,6 @@ static int key_validate_ext(const struct sadb_ext *, i
 static int key_align(struct mbuf *, struct sadb_msghdr *);
 static struct mbuf *key_setlifetime(struct seclifetime *, uint16_t);
 static struct mbuf *key_setkey(struct seckey *, uint16_t);
-static int xform_init(struct secasvar *, u_short);
 
 static void spdcache_init(void);
 static void spdcache_clear(void);
@@ -6167,7 +6157,7 @@ key_delete_all(struct socket *so, struct mbuf *m,
  * Larval SAs have not initialized tdb_xform, so it is safe to leave them
  * here when xform disappears.
  */
-static void
+void
 key_delete_xform(const struct xformsw *xsp)
 {
        struct secasvar_queue drainq;
@@ -8335,7 +8325,6 @@ key_init(void)
        if (!IS_DEFAULT_VNET(curvnet))
                return;
 
-       XFORMS_LOCK_INIT();
        SPTREE_LOCK_INIT();
        REGTREE_LOCK_INIT();
        SAHTREE_LOCK_INIT();
@@ -8458,7 +8447,6 @@ key_destroy(void)
 #ifndef IPSEC_DEBUG2
        callout_drain(&key_timer);
 #endif
-       XFORMS_LOCK_DESTROY();
        SPTREE_LOCK_DESTROY();
        REGTREE_LOCK_DESTROY();
        SAHTREE_LOCK_DESTROY();
@@ -8615,72 +8603,5 @@ comp_algorithm_lookup(int alg)
                if (alg == supported_calgs[i].sadb_alg)
                        return (supported_calgs[i].xform);
        return (NULL);
-}
-
-/*
- * Register a transform.
- */
-static int
-xform_register(struct xformsw* xsp)
-{
-       struct xformsw *entry;
-
-       XFORMS_LOCK();
-       LIST_FOREACH(entry, &xforms, chain) {
-               if (entry->xf_type == xsp->xf_type) {
-                       XFORMS_UNLOCK();
-                       return (EEXIST);
-               }
-       }
-       LIST_INSERT_HEAD(&xforms, xsp, chain);
-       XFORMS_UNLOCK();
-       return (0);
-}
-
-void
-xform_attach(void *data)
-{
-       struct xformsw *xsp = (struct xformsw *)data;
-
-       if (xform_register(xsp) != 0)
-               printf("%s: failed to register %s xform\n", __func__,
-                   xsp->xf_name);
-}
-
-void
-xform_detach(void *data)
-{
-       struct xformsw *xsp = (struct xformsw *)data;
-
-       XFORMS_LOCK();
-       LIST_REMOVE(xsp, chain);
-       XFORMS_UNLOCK();
-
-       /* Delete all SAs related to this xform. */
-       key_delete_xform(xsp);
-}
-
-/*
- * Initialize transform support in an sav.
- */
-static int
-xform_init(struct secasvar *sav, u_short xftype)
-{
-       struct xformsw *entry;
-       int ret;
-
-       IPSEC_ASSERT(sav->tdb_xform == NULL,
-           ("tdb_xform is already initialized"));
-
-       ret = EINVAL;
-       XFORMS_LOCK();
-       LIST_FOREACH(entry, &xforms, chain) {
-           if (entry->xf_type == xftype) {
-                   ret = (*entry->xf_init)(sav, entry);
-                   break;
-           }
-       }
-       XFORMS_UNLOCK();
-       return (ret);
 }
 

Modified: head/sys/netipsec/key.h
==============================================================================
--- head/sys/netipsec/key.h     Wed Sep 26 14:32:36 2018        (r338944)
+++ head/sys/netipsec/key.h     Wed Sep 26 14:47:51 2018        (r338945)
@@ -46,6 +46,7 @@ struct sadb_msg;
 struct sadb_x_policy;
 struct secasindex;
 union sockaddr_union;
+struct xformsw;
 
 struct secpolicy *key_newsp(void);
 struct secpolicy *key_allocsp(struct secpolicyindex *, u_int);
@@ -73,6 +74,8 @@ int key_sockaddrcmp_withmask(const struct sockaddr *, 
 
 int key_register_ifnet(struct secpolicy **, u_int);
 void key_unregister_ifnet(struct secpolicy **, u_int);
+
+void key_delete_xform(const struct xformsw *);
 
 extern u_long key_random(void);
 extern void key_randomfill(void *, size_t);

Modified: head/sys/netipsec/subr_ipsec.c
==============================================================================
--- head/sys/netipsec/subr_ipsec.c      Wed Sep 26 14:32:36 2018        
(r338944)
+++ head/sys/netipsec/subr_ipsec.c      Wed Sep 26 14:47:51 2018        
(r338945)
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
 #include <netipsec/ipsec6.h>
 #include <netipsec/key.h>
 #include <netipsec/key_debug.h>
+#include <netipsec/xform.h>
 
 #include <machine/atomic.h>
 /*
@@ -124,14 +125,6 @@ ipsec6_setsockaddrs(const struct mbuf *m, union sockad
 }
 #endif
 
-#ifdef IPSEC_SUPPORT
-/*
- * IPSEC_SUPPORT - loading of ipsec.ko and tcpmd5.ko is supported.
- * IPSEC + IPSEC_SUPPORT - loading tcpmd5.ko is supported.
- * IPSEC + TCP_SIGNATURE - all is build in the kernel, do not build
- *   IPSEC_SUPPORT.
- */
-#if !defined(IPSEC) || !defined(TCP_SIGNATURE)
 #define        IPSEC_MODULE_INCR       2
 static int
 ipsec_kmod_enter(volatile u_int *cntr)
@@ -171,6 +164,83 @@ ipsec_kmod_drain(volatile u_int *cntr)
                pause("ipsecd", hz/2);
 }
 
+static LIST_HEAD(xforms_list, xformsw) xforms = LIST_HEAD_INITIALIZER();
+static struct mtx xforms_lock;
+MTX_SYSINIT(xfroms_list, &xforms_lock, "IPsec transforms list", MTX_DEF);
+#define        XFORMS_LOCK()           mtx_lock(&xforms_lock)
+#define        XFORMS_UNLOCK()         mtx_unlock(&xforms_lock)
+
+void
+xform_attach(void *data)
+{
+       struct xformsw *xsp, *entry;
+
+       xsp = (struct xformsw *)data;
+       XFORMS_LOCK();
+       LIST_FOREACH(entry, &xforms, chain) {
+               if (entry->xf_type == xsp->xf_type) {
+                       XFORMS_UNLOCK();
+                       printf("%s: failed to register %s xform\n",
+                           __func__, xsp->xf_name);
+                       return;
+               }
+       }
+       LIST_INSERT_HEAD(&xforms, xsp, chain);
+       xsp->xf_cntr = IPSEC_MODULE_ENABLED;
+       XFORMS_UNLOCK();
+}
+
+void
+xform_detach(void *data)
+{
+       struct xformsw *xsp = (struct xformsw *)data;
+
+       XFORMS_LOCK();
+       LIST_REMOVE(xsp, chain);
+       XFORMS_UNLOCK();
+
+       /* Delete all SAs related to this xform. */
+       key_delete_xform(xsp);
+       if (xsp->xf_cntr & IPSEC_MODULE_ENABLED)
+               ipsec_kmod_drain(&xsp->xf_cntr);
+}
+
+/*
+ * Initialize transform support in an sav.
+ */
+int
+xform_init(struct secasvar *sav, u_short xftype)
+{
+       struct xformsw *entry;
+       int ret;
+
+       IPSEC_ASSERT(sav->tdb_xform == NULL,
+           ("tdb_xform is already initialized"));
+
+       XFORMS_LOCK();
+       LIST_FOREACH(entry, &xforms, chain) {
+               if (entry->xf_type == xftype) {
+                       ret = ipsec_kmod_enter(&entry->xf_cntr);
+                       XFORMS_UNLOCK();
+                       if (ret != 0)
+                               return (ret);
+                       ret = (*entry->xf_init)(sav, entry);
+                       ipsec_kmod_exit(&entry->xf_cntr);
+                       return (ret);
+               }
+       }
+       XFORMS_UNLOCK();
+       return (EINVAL);
+}
+
+#ifdef IPSEC_SUPPORT
+/*
+ * IPSEC_SUPPORT - loading of ipsec.ko and tcpmd5.ko is supported.
+ * IPSEC + IPSEC_SUPPORT - loading tcpmd5.ko is supported.
+ * IPSEC + TCP_SIGNATURE - all is build in the kernel, do not build
+ *   IPSEC_SUPPORT.
+ */
+#if !defined(IPSEC) || !defined(TCP_SIGNATURE)
 #define        METHOD_DECL(...)        __VA_ARGS__
 #define        METHOD_ARGS(...)        __VA_ARGS__
 #define        IPSEC_KMOD_METHOD(type, name, sc, method, decl, args)           
\

Modified: head/sys/netipsec/xform.h
==============================================================================
--- head/sys/netipsec/xform.h   Wed Sep 26 14:32:36 2018        (r338944)
+++ head/sys/netipsec/xform.h   Wed Sep 26 14:47:51 2018        (r338945)
@@ -86,14 +86,16 @@ struct xform_data {
 #define        XF_IPCOMP       6       /* IPCOMP */
 
 struct xformsw {
-       u_short xf_type;                /* xform ID */
-       char    *xf_name;               /* human-readable name */
+       u_short                 xf_type;        /* xform ID */
+       const char              *xf_name;       /* human-readable name */
        int     (*xf_init)(struct secasvar*, struct xformsw*);  /* setup */
        int     (*xf_zeroize)(struct secasvar*);                /* cleanup */
        int     (*xf_input)(struct mbuf*, struct secasvar*,     /* input */
                        int, int);
        int     (*xf_output)(struct mbuf*,                      /* output */
            struct secpolicy *, struct secasvar *, u_int, int, int);
+
+       volatile u_int          xf_cntr;
        LIST_ENTRY(xformsw)     chain;
 };
 
@@ -103,6 +105,7 @@ const struct comp_algo * comp_algorithm_lookup(int);
 
 void xform_attach(void *);
 void xform_detach(void *);
+int xform_init(struct secasvar *, u_short);
 
 struct cryptoini;
 /* XF_AH */
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to