ipsec4_common_input_cb(m, sav, skip, protoff, + &sahtree_tracker); break; #endif default: @@ -673,6 +678,7 @@ esp_input_cb(struct cryptop *crp) CURVNET_RESTORE(); return error; bad: + ipsec_sahtree_runlock(&sahtree_tracker); if (sav != NULL) key_freesav(&sav); if (m != NULL) diff --git a/sys/netipsec/xform_ipcomp.c b/sys/netipsec/xform_ipcomp.c index 05a01b75e0bb..61fb9413a01a 100644 --- a/sys/netipsec/xform_ipcomp.c +++ b/sys/netipsec/xform_ipcomp.c @@ -283,6 +283,7 @@ static int ipcomp_input_cb(struct cryptop *crp) { IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); + struct rm_priotracker sahtree_tracker; struct xform_data *xd; struct mbuf *m; struct secasvar *sav; @@ -300,6 +301,14 @@ ipcomp_input_cb(struct cryptop *crp) skip = xd->skip; protoff = xd->protoff; cryptoid = xd->cryptoid; + ipsec_sahtree_rlock(&sahtree_tracker); + if (sav->state >= SADB_SASTATE_DEAD) { + /* saidx is freed */ + DPRINTF(("%s: dead SA %p spi %#x\n", __func__, sav, sav->spi)); + IPCOMPSTAT_INC(ipcomps_notdb); + error = ESRCH; + goto bad; + } saidx = &sav->sah->saidx; IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET || saidx->dst.sa.sa_family == AF_INET6, @@ -365,12 +374,14 @@ ipcomp_input_cb(struct cryptop *crp) switch (saidx->dst.sa.sa_family) { #ifdef INET6 case AF_INET6: - error = ipsec6_common_input_cb(m, sav, skip, protoff); + error = ipsec6_common_input_cb(m, sav, skip, protoff, + &sahtree_tracker); break; #endif #ifdef INET case AF_INET: - error = ipsec4_common_input_cb(m, sav, skip, protoff); + error = ipsec4_common_input_cb(m, sav, skip, protoff, + &sahtree_tracker); break; #endif default: @@ -380,6 +391,7 @@ ipcomp_input_cb(struct cryptop *crp) CURVNET_RESTORE(); return error; bad: + ipsec_sahtree_runlock(&sahtree_tracker); CURVNET_RESTORE(); if (sav != NULL) key_freesav(&sav);