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
This commit is contained in:
Andrey V. Elsukov 2015-09-30 08:16:33 +00:00
parent 3142b37664
commit f367798498
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=288418
6 changed files with 7 additions and 20 deletions

View File

@ -199,9 +199,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

View File

@ -200,9 +200,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

View File

@ -166,10 +166,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. */
@ -177,11 +173,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
@ -189,11 +181,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

View File

@ -1068,6 +1068,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;

View File

@ -874,6 +874,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;

View File

@ -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;