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