svn commit: r311785 - projects/ipsec/sys/netipsec

Andrey V. Elsukov ae at FreeBSD.org
Mon Jan 9 13:12:11 UTC 2017


Author: ae
Date: Mon Jan  9 13:12:09 2017
New Revision: 311785
URL: https://svnweb.freebsd.org/changeset/base/311785

Log:
  Change IPsec default policy to be allocated on module initialization,
  instead of using static variable. Since each security policy can be
  cached in PCB, static variable becomes invalid after module unload.
  When module is loaded again, the cache will be invalidated, and this
  leads to access to invalid memory. Now default security policy is
  allocated on module initialization like all another policies. And
  such policies will be kept until last reference isn't released on
  next cache invalidation.
  
  Also modify corresponding sysctl variables to be SYSCTL_PROC.

Modified:
  projects/ipsec/sys/netipsec/ipsec.c
  projects/ipsec/sys/netipsec/ipsec.h
  projects/ipsec/sys/netipsec/ipsec_mod.c

Modified: projects/ipsec/sys/netipsec/ipsec.c
==============================================================================
--- projects/ipsec/sys/netipsec/ipsec.c	Mon Jan  9 11:37:25 2017	(r311784)
+++ projects/ipsec/sys/netipsec/ipsec.c	Mon Jan  9 13:12:09 2017	(r311785)
@@ -123,8 +123,24 @@ static VNET_DEFINE(int, ip4_filtertunnel
 #define	V_ip4_filtertunnel VNET(ip4_filtertunnel)
 static VNET_DEFINE(int, check_policy_history) = 0;
 #define	V_check_policy_history	VNET(check_policy_history)
-static VNET_DEFINE(struct secpolicy, def_policy);
+static VNET_DEFINE(struct secpolicy *, def_policy) = NULL;
 #define	V_def_policy	VNET(def_policy)
+static int
+sysctl_def_policy(SYSCTL_HANDLER_ARGS)
+{
+	int error, value;
+
+	value = V_def_policy->policy;
+	error = sysctl_handle_int(oidp, &value, 0, req);
+	if (error == 0) {
+		if (value != IPSEC_POLICY_DISCARD &&
+		    value != IPSEC_POLICY_NONE)
+			return (EINVAL);
+		V_def_policy->policy = value;
+	}
+	return (error);
+}
+
 /*
  * Crypto support requirements:
  *
@@ -148,8 +164,8 @@ FEATURE(ipsec_natt, "UDP Encapsulation o
 SYSCTL_DECL(_net_inet_ipsec);
 
 /* net.inet.ipsec */
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY, def_policy,
-	CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(def_policy).policy, 0,
+SYSCTL_PROC(_net_inet_ipsec, IPSECCTL_DEF_POLICY, def_policy,
+	CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_RW, 0, 0, sysctl_def_policy, "I",
 	"IPsec default policy.");
 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
 	CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_esp_trans_deflev), 0,
@@ -229,8 +245,8 @@ static VNET_DEFINE(int, ip6_filtertunnel
 SYSCTL_DECL(_net_inet6_ipsec6);
 
 /* net.inet6.ipsec6 */
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, def_policy,
-	CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(def_policy).policy, 0,
+SYSCTL_PROC(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, def_policy,
+	CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_RW, 0, 0, sysctl_def_policy, "I",
 	"IPsec default policy.");
 SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
 	CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_esp_trans_deflev), 0,
@@ -272,17 +288,9 @@ static void ipsec6_setspidx_ipaddr(const
 static struct secpolicy *
 key_allocsp_default(void)
 {
-	struct secpolicy *sp;
 
-	sp = &V_def_policy;
-	if (sp->policy != IPSEC_POLICY_DISCARD &&
-	    sp->policy != IPSEC_POLICY_NONE) {
-		ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n",
-		    sp->policy, IPSEC_POLICY_NONE));
-		sp->policy = IPSEC_POLICY_NONE;
-	}
-	key_addref(sp);
-	return (sp);
+	key_addref(V_def_policy);
+	return (V_def_policy);
 }
 
 static void
@@ -1345,16 +1353,38 @@ ipsec_updateid(struct secasvar *sav, uin
 	return (0);
 }
 
+int
+ipsec_initialized(void)
+{
+
+	return (V_def_policy != NULL);
+}
+
 static void
 def_policy_init(const void *unused __unused)
 {
 
-	bzero(&V_def_policy, sizeof(struct secpolicy));
-	V_def_policy.policy = IPSEC_POLICY_NONE;
-	V_def_policy.refcnt = 1;
+	V_def_policy = key_newsp();
+	if (V_def_policy != NULL) {
+		V_def_policy->policy = IPSEC_POLICY_NONE;
+		/* Force INPCB SP cache invalidation */
+		key_bumpspgen();
+	} else
+		printf("%s: failed to initialize default policy\n", __func__);
+}
+
 
-	/* Force INPCB SP cache invalidation */
-	key_bumpspgen();
+static void
+def_policy_uninit(const void *unused __unused)
+{
+
+	if (V_def_policy != NULL) {
+		key_freesp(&V_def_policy);
+		key_bumpspgen();
+	}
 }
+
 VNET_SYSINIT(def_policy_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST,
     def_policy_init, NULL);
+VNET_SYSUNINIT(def_policy_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST,
+    def_policy_uninit, NULL);

Modified: projects/ipsec/sys/netipsec/ipsec.h
==============================================================================
--- projects/ipsec/sys/netipsec/ipsec.h	Mon Jan  9 11:37:25 2017	(r311784)
+++ projects/ipsec/sys/netipsec/ipsec.h	Mon Jan  9 13:12:09 2017	(r311785)
@@ -319,6 +319,7 @@ int udp_ipsec_pcbctl(struct inpcb *, str
 int ipsec_chkreplay(uint32_t, struct secasvar *);
 int ipsec_updatereplay(uint32_t, struct secasvar *);
 int ipsec_updateid(struct secasvar *, uint64_t *, uint64_t *);
+int ipsec_initialized(void);
 
 void ipsec_setspidx_inpcb(struct inpcb *, struct secpolicyindex *, u_int);
 

Modified: projects/ipsec/sys/netipsec/ipsec_mod.c
==============================================================================
--- projects/ipsec/sys/netipsec/ipsec_mod.c	Mon Jan  9 11:37:25 2017	(r311784)
+++ projects/ipsec/sys/netipsec/ipsec_mod.c	Mon Jan  9 13:12:09 2017	(r311785)
@@ -107,6 +107,8 @@ ipsec_modevent(module_t mod, int type, v
 	switch (type) {
 	case MOD_LOAD:
 		/* All xforms are registered via SYSINIT */
+		if (!ipsec_initialized())
+			return (ENOMEM);
 #ifdef KLD_MODULE
 #ifdef INET
 		ipsec_support_enable(ipv4_ipsec_support, &ipv4_methods);


More information about the svn-src-projects mailing list