Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Sep 2018 14:47:52 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r338945 - head/sys/netipsec
Message-ID:  <201809261447.w8QElqpD015069@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201809261447.w8QElqpD015069>