]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
Take extra reference to security policy before calling crypto_dispatch().
authorae <ae@FreeBSD.org>
Wed, 30 Sep 2015 08:16:33 +0000 (08:16 +0000)
committerae <ae@FreeBSD.org>
Wed, 30 Sep 2015 08:16:33 +0000 (08:16 +0000)
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

sys/netinet/ip_ipsec.c
sys/netinet6/ip6_ipsec.c
sys/netipsec/ipsec_output.c
sys/netipsec/xform_ah.c
sys/netipsec/xform_esp.c
sys/netipsec/xform_ipcomp.c

index 47f683ddd71c3a8231529f3616c7ee59ea180024..546f802f96177cc2dc41abae94f298ccf08cc9cb 100644 (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
index d7f08e91537c02988b7f1dd0e6e8b2c35c636f95..a99f1db14e8e6ffc105c5f12e7d2577bc04beef6 100644 (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
index a6611a7e7fcb1e49dc2204c8de3e3cd8207652db..f5cdf5a417b62e399e99daa209b15272c2d859fd 100644 (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
index 350a735a89b3c3f37e00a2aa7cc75127830f94c6..0d39eeba49ad97a7bd43fa046604f212e80bc687 100644 (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;
index a48c0386b9afb1a9911acec00b906ed08a50826b..9f645c0c4f55be20b97fad54d58ef40e7c7dd168 100644 (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;
index ef460cdc90dc159172af4d271ffd24a15d634983..122fc726137859a3ec3792e9499ec357dd01942b 100644 (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;