summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuiz Otavio O Souza <luiz@netgate.com>2016-05-11 12:48:11 -0500
committerLuiz Otavio O Souza <luiz@netgate.com>2016-05-12 10:59:34 -0500
commitb2fbeb687ab88416fde1db788240cd4694bf340b (patch)
tree04ba6079b36282e4cff7fbc8f53f47f8836068e3
parent67d971cff8b345311dc2317f112dd3c1b4a7fadf (diff)
downloadFreeBSD-src-b2fbeb687ab88416fde1db788240cd4694bf340b.zip
FreeBSD-src-b2fbeb687ab88416fde1db788240cd4694bf340b.tar.gz
MFC r288418:
Take extra reference to security policy before calling crypto_dispatch(). Currently we perform crypto requests for IPSEC synchronous for most of crypto providers (software, aesni) and only VIA padlock calls crypto callback asynchronous. In synchronous mode it is possible, that security policy will be removed during the processing crypto request. And crypto callback will release the last reference to SP. Then upon return into ipsec[46]_process_packet() IPSECREQUEST_UNLOCK() will be called to already freed request. To prevent this we will take extra reference to SP. PR: 201876 Sponsored by: Yandex LLC TAG: IPSEC-HEAD (cherry picked from commit 3e1742ed6cd844d82787f2fa5cd57652805c6b34)
-rw-r--r--sys/netinet/ip_ipsec.c4
-rw-r--r--sys/netinet6/ip6_ipsec.c4
-rw-r--r--sys/netipsec/ipsec_output.c16
-rw-r--r--sys/netipsec/xform_ah.c1
-rw-r--r--sys/netipsec/xform_esp.c1
-rw-r--r--sys/netipsec/xform_ipcomp.c1
6 files changed, 7 insertions, 20 deletions
diff --git a/sys/netinet/ip_ipsec.c b/sys/netinet/ip_ipsec.c
index df25235..4a702d7 100644
--- a/sys/netinet/ip_ipsec.c
+++ b/sys/netinet/ip_ipsec.c
@@ -202,9 +202,7 @@ ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *error)
/* NB: callee frees mbuf */
*error = ipsec4_process_packet(*m, sp->req);
- /* Release SP if an error occured */
- if (*error != 0)
- KEY_FREESP(&sp);
+ KEY_FREESP(&sp);
if (*error == EJUSTRETURN) {
/*
* We had a SP with a level of 'use' and no SA. We
diff --git a/sys/netinet6/ip6_ipsec.c b/sys/netinet6/ip6_ipsec.c
index 19a0853..e10f274 100644
--- a/sys/netinet6/ip6_ipsec.c
+++ b/sys/netinet6/ip6_ipsec.c
@@ -212,9 +212,7 @@ ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *error)
/* NB: callee frees mbuf */
*error = ipsec6_process_packet(*m, sp->req);
- /* Release SP if an error occured */
- if (*error != 0)
- KEY_FREESP(&sp);
+ KEY_FREESP(&sp);
if (*error == EJUSTRETURN) {
/*
* We had a SP with a level of 'use' and no SA. We
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
index 7fc61ac..7045170 100644
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -165,10 +165,6 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
* If this is a problem we'll need to introduce a queue
* to set the packet on so we can unwind the stack before
* doing further processing.
- *
- * If ipsec[46]_process_packet() will successfully queue
- * the request, we need to take additional reference to SP,
- * because xform callback will release reference.
*/
if (isr->next) {
/* XXX-BZ currently only support same AF bundles. */
@@ -176,11 +172,7 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
#ifdef INET
case AF_INET:
IPSECSTAT_INC(ips_out_bundlesa);
- key_addref(isr->sp);
- error = ipsec4_process_packet(m, isr->next);
- if (error != 0)
- KEY_FREESP(&isr->sp);
- return (error);
+ return (ipsec4_process_packet(m, isr->next));
/* NOTREACHED */
#endif
#ifdef notyet
@@ -188,11 +180,7 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
case AF_INET6:
/* XXX */
IPSEC6STAT_INC(ips_out_bundlesa);
- key_addref(isr->sp);
- error = ipsec6_process_packet(m, isr->next);
- if (error != 0)
- KEY_FREESP(&isr->sp);
- return (error);
+ return (ipsec6_process_packet(m, isr->next));
/* NOTREACHED */
#endif /* INET6 */
#endif
diff --git a/sys/netipsec/xform_ah.c b/sys/netipsec/xform_ah.c
index 6829d59..0512d21 100644
--- a/sys/netipsec/xform_ah.c
+++ b/sys/netipsec/xform_ah.c
@@ -1066,6 +1066,7 @@ ah_output(struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp,
crp->crp_opaque = (caddr_t) tc;
/* These are passed as-is to the callback. */
+ key_addref(isr->sp);
tc->tc_isr = isr;
KEY_ADDREFSA(sav);
tc->tc_sav = sav;
diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c
index f1c1eaf..694545d 100644
--- a/sys/netipsec/xform_esp.c
+++ b/sys/netipsec/xform_esp.c
@@ -873,6 +873,7 @@ esp_output(struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp,
}
/* Callback parameters */
+ key_addref(isr->sp);
tc->tc_isr = isr;
KEY_ADDREFSA(sav);
tc->tc_sav = sav;
diff --git a/sys/netipsec/xform_ipcomp.c b/sys/netipsec/xform_ipcomp.c
index a5d1e57..605fff9 100644
--- a/sys/netipsec/xform_ipcomp.c
+++ b/sys/netipsec/xform_ipcomp.c
@@ -449,6 +449,7 @@ ipcomp_output(struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp,
goto bad;
}
+ key_addref(isr->sp);
tc->tc_isr = isr;
KEY_ADDREFSA(sav);
tc->tc_sav = sav;
OpenPOWER on IntegriCloud