Page MenuHomeFreeBSD

D54325.id168517.diff
No OneTemporary

D54325.id168517.diff

diff --git a/sys/net/if_ipsec.c b/sys/net/if_ipsec.c
--- a/sys/net/if_ipsec.c
+++ b/sys/net/if_ipsec.c
@@ -450,7 +450,8 @@
}
int
-ipsec_if_input(struct mbuf *m, struct secasvar *sav, uint32_t af)
+ipsec_if_input(struct mbuf *m, struct secasvar *sav, uint32_t af,
+ struct rm_priotracker *sahtree_tracker)
{
IPSEC_RLOCK_TRACKER;
struct secasindex *saidx;
@@ -459,13 +460,16 @@
if (sav->state != SADB_SASTATE_MATURE &&
sav->state != SADB_SASTATE_DYING) {
+ ipsec_sahtree_runlock(sahtree_tracker);
m_freem(m);
return (ENETDOWN);
}
if (sav->sah->saidx.mode != IPSEC_MODE_TUNNEL ||
- sav->sah->saidx.proto != IPPROTO_ESP)
+ sav->sah->saidx.proto != IPPROTO_ESP) {
+ ipsec_sahtree_runlock(sahtree_tracker);
return (0);
+ }
IPSEC_RLOCK();
CK_LIST_FOREACH(sc, ipsec_idhash(sav->sah->saidx.reqid), idhash) {
@@ -487,6 +491,7 @@
}
if (sc == NULL) {
IPSEC_RUNLOCK();
+ ipsec_sahtree_runlock(sahtree_tracker);
/* Tunnel was not found. Nothing to do. */
return (0);
}
@@ -494,6 +499,7 @@
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
(ifp->if_flags & IFF_UP) == 0) {
IPSEC_RUNLOCK();
+ ipsec_sahtree_runlock(sahtree_tracker);
m_freem(m);
return (ENETDOWN);
}
@@ -503,6 +509,8 @@
*/
m->m_pkthdr.rcvif = ifp;
+ ipsec_sahtree_runlock(sahtree_tracker);
+
m_clrprotoflags(m);
M_SETFIB(m, ifp->if_fib);
BPF_MTAP2(ifp, &af, sizeof(af), m);
diff --git a/sys/netipsec/ipsec.h b/sys/netipsec/ipsec.h
--- a/sys/netipsec/ipsec.h
+++ b/sys/netipsec/ipsec.h
@@ -330,12 +330,14 @@
struct inpcb;
struct ip;
struct m_tag;
+struct rm_priotracker;
struct secasvar;
struct sockopt;
struct tcphdr;
union sockaddr_union;
-int ipsec_if_input(struct mbuf *, struct secasvar *, uint32_t);
+int ipsec_if_input(struct mbuf *, struct secasvar *, uint32_t,
+ struct rm_priotracker *);
struct ipsecrequest *ipsec_newisr(void);
void ipsec_delisr(struct ipsecrequest *);
@@ -357,7 +359,8 @@
void ipsec4_setsockaddrs(const struct mbuf *, const struct ip *,
union sockaddr_union *, union sockaddr_union *);
-int ipsec4_common_input_cb(struct mbuf *, struct secasvar *, int, int);
+int ipsec4_common_input_cb(struct mbuf *, struct secasvar *, int, int,
+ struct rm_priotracker *sahtree_tracker);
int ipsec4_check_pmtu(struct ifnet *, struct mbuf *, struct ip *ip1,
struct secpolicy *, int);
int ipsec4_process_packet(struct ifnet *, struct mbuf *, struct ip *ip1,
diff --git a/sys/netipsec/ipsec6.h b/sys/netipsec/ipsec6.h
--- a/sys/netipsec/ipsec6.h
+++ b/sys/netipsec/ipsec6.h
@@ -60,12 +60,15 @@
#define V_ip6_ipsec_ecn VNET(ip6_ipsec_ecn)
struct inpcb;
+struct rm_priotracker;
+
struct secpolicy *ipsec6_checkpolicy(const struct mbuf *,
struct inpcb *, int *, int);
void ipsec6_setsockaddrs(const struct mbuf *, union sockaddr_union *,
union sockaddr_union *);
-int ipsec6_common_input_cb(struct mbuf *, struct secasvar *, int, int);
+int ipsec6_common_input_cb(struct mbuf *, struct secasvar *, int, int,
+ struct rm_priotracker *sahtree_tracker);
int ipsec6_check_pmtu(struct ifnet *, struct mbuf *, struct secpolicy *, int);
int ipsec6_process_packet(struct ifnet *, struct mbuf *, struct secpolicy *,
struct inpcb *, u_long);
diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c
--- a/sys/netipsec/ipsec_input.c
+++ b/sys/netipsec/ipsec_input.c
@@ -339,7 +339,7 @@
*/
int
ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
- int protoff)
+ int protoff, struct rm_priotracker *sahtree_tracker)
{
IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
struct epoch_tracker et;
@@ -492,7 +492,9 @@
/* Handle virtual tunneling interfaces */
if (saidx->mode == IPSEC_MODE_TUNNEL)
- error = ipsec_if_input(m, sav, af);
+ error = ipsec_if_input(m, sav, af, sahtree_tracker);
+ else
+ ipsec_sahtree_runlock(sahtree_tracker);
if (error == 0) {
error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m);
if (error) {
@@ -507,6 +509,7 @@
bad:
NET_EPOCH_EXIT(et);
bad_noepoch:
+ ipsec_sahtree_runlock(sahtree_tracker);
key_freesav(&sav);
if (m != NULL)
m_freem(m);
@@ -590,7 +593,7 @@
*/
int
ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
- int protoff)
+ int protoff, struct rm_priotracker *sahtree_tracker)
{
IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
struct epoch_tracker et;
@@ -734,7 +737,9 @@
}
/* Handle virtual tunneling interfaces */
if (saidx->mode == IPSEC_MODE_TUNNEL)
- error = ipsec_if_input(m, sav, af);
+ error = ipsec_if_input(m, sav, af, sahtree_tracker);
+ else
+ ipsec_sahtree_runlock(sahtree_tracker);
if (error == 0) {
error = netisr_queue_src(isr_prot,
(uintptr_t)sav->spi, m);
@@ -748,6 +753,9 @@
key_freesav(&sav);
return (error);
}
+
+ ipsec_sahtree_runlock(sahtree_tracker);
+
/*
* See the end of ip6_input for this logic.
* IPPROTO_IPV[46] case will be processed just like other ones
@@ -787,6 +795,7 @@
return (0);
bad:
NET_EPOCH_EXIT(et);
+ ipsec_sahtree_runlock(sahtree_tracker);
key_freesav(&sav);
if (m)
m_freem(m);
diff --git a/sys/netipsec/xform_ah.c b/sys/netipsec/xform_ah.c
--- a/sys/netipsec/xform_ah.c
+++ b/sys/netipsec/xform_ah.c
@@ -692,6 +692,7 @@
{
IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
unsigned char calc[AH_ALEN_MAX];
+ struct rm_priotracker sahtree_tracker;
struct mbuf *m;
struct xform_data *xd;
struct secasvar *sav;
@@ -711,6 +712,14 @@
nxt = xd->nxt;
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));
+ AHSTAT_INC(ahs_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,
@@ -808,12 +817,14 @@
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:
@@ -823,6 +834,7 @@
CURVNET_RESTORE();
return error;
bad:
+ ipsec_sahtree_runlock(&sahtree_tracker);
CURVNET_RESTORE();
if (sav)
key_freesav(&sav);
diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c
--- a/sys/netipsec/xform_esp.c
+++ b/sys/netipsec/xform_esp.c
@@ -492,6 +492,7 @@
esp_input_cb(struct cryptop *crp)
{
IPSEC_DEBUG_DECLARE(char buf[128]);
+ struct rm_priotracker sahtree_tracker;
uint8_t lastthree[3];
const struct auth_hash *esph;
struct mbuf *m;
@@ -507,6 +508,7 @@
xd = crp->crp_opaque;
CURVNET_SET(xd->vnet);
sav = xd->sav;
+ 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));
@@ -527,6 +529,7 @@
if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0)
crypto_freesession(cryptoid);
xd->cryptoid = crp->crp_session;
+ ipsec_sahtree_runlock(&sahtree_tracker);
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
@@ -658,12 +661,14 @@
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:
@@ -673,6 +678,7 @@
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
--- a/sys/netipsec/xform_ipcomp.c
+++ b/sys/netipsec/xform_ipcomp.c
@@ -283,6 +283,7 @@
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 @@
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 @@
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 @@
CURVNET_RESTORE();
return error;
bad:
+ ipsec_sahtree_runlock(&sahtree_tracker);
CURVNET_RESTORE();
if (sav != NULL)
key_freesav(&sav);

File Metadata

Mime Type
text/plain
Expires
Fri, Jul 24, 2:16 AM (12 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35425188
Default Alt Text
D54325.id168517.diff (9 KB)

Event Timeline