From nobody Mon Dec 29 01:01:46 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4dfdGL3tsSz6LQ3C for ; Mon, 29 Dec 2025 01:01:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4dfdGL38Vkz3WW0 for ; Mon, 29 Dec 2025 01:01:46 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1766970106; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=+ZQ4GyMxRuG4p0JV0DGcbSR6P028Wlgp0NA6ht1v8cg=; b=kpZnj510UMpYXeGbeViOw1MjvbassvAu7cfaNTmWd9a/r+Jtx+Hcj/2k1nbef1uFtKD45D r2gzlfhxj8plADZTJuJEiBCi4sNNM7VNZk9R0RqQWHmSeL00Dx6skptXAXUffBNuNmzLZT YivpDrquoA0F7OonpxFBiGpT/qJLC338uH52gEnkI6wHOXDgWoNARQlWlJ+5bSIoHoYhDm adlIR7OO17ErQhrbFJ1p3ExgZMbWK3QFTVmMKgcLuoxIUXkDiID6EXMf73aJdxFbFtiUwi Cn8Xrkpg9qeC631cmNcNZFd7Qa1AiRCG50m5SD4jWtwxslkmRXVZi52RQaa86g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1766970106; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=+ZQ4GyMxRuG4p0JV0DGcbSR6P028Wlgp0NA6ht1v8cg=; b=WohZ/9QUljCjkUo1PByZpLo1yZSgfx66XcaxZNU0DHOUIuwjqIMcCQwOo5Hwz6iUd3KjAp 3U1x+zg/padN5qqqjA80r7I8Dcxe+6JINibpfs1VewJo/5In3maBsHNa6zZ/nCWqcN7OCn UIblbZd1K5+pFOFLMtH0Qv8wCKBhcR03QHEIg7YafyFnt5VonlyRcGdeRxXAgxpKqUs/Vc Z2+u+DvjJiKG08GG432KANRO4IsV6oIu6NCIIpO17D2M/GmQBUEdToKYPhfAlw1itXB7zS bm6MbvKMCM47KGmR1luIc5sHapW/LeHeHKjI1lPrJZlqlmlmZS1sOC6xJHj63g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1766970106; a=rsa-sha256; cv=none; b=hbPpfwaUfrP9hzmckyvEoainOn0ZoXaM2mg0tKQjvt4VdeF9BzQas2VSoTLbgGupoKglEx xl+oOA2GXrpzhFf43CF2e8FF8NdiL5tiFFer/8MeIp6R8bT6PO6mCq3Q7Rr+UyC6504k8B 57CFweOBK4Dqml97x+OjJaANjLSB+wk7xoH1zzB+T1TIVOwJssuQVjKfzbnEJ+DIvlAWwJ Iqk7QS8pDObJG/DJW64CKx85EPVzt364G07KWHhcMvNx/hUEl956Bb9TQcKXMua3Ymy21w JosbjlpD09z5msCXSIT/LXsc9MMRSQg5adjDdjN35qPxY5fYBBOA3/pMLiB1ow== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4dfdGL2fqXz17bf for ; Mon, 29 Dec 2025 01:01:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 379bd by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 29 Dec 2025 01:01:46 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Konstantin Belousov Subject: git: b86fc3284bf8 - stable/15 - sys/netipsec: ensure sah stability during input callback processing List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: b86fc3284bf8eff23cc2606bf7ab0c8117e6023e Auto-Submitted: auto-generated Date: Mon, 29 Dec 2025 01:01:46 +0000 Message-Id: <6951d2fa.379bd.5b3e126@gitrepo.freebsd.org> The branch stable/15 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=b86fc3284bf8eff23cc2606bf7ab0c8117e6023e commit b86fc3284bf8eff23cc2606bf7ab0c8117e6023e Author: Konstantin Belousov AuthorDate: 2025-12-09 08:55:11 +0000 Commit: Konstantin Belousov CommitDate: 2025-12-29 00:57:03 +0000 sys/netipsec: ensure sah stability during input callback processing (cherry picked from commit 183513d15f2290a42b542753aaffe9de2152575b) --- sys/net/if_ipsec.c | 12 ++++++++++-- sys/netipsec/ipsec.h | 7 +++++-- sys/netipsec/ipsec6.h | 5 ++++- sys/netipsec/ipsec_input.c | 17 +++++++++++++---- sys/netipsec/xform_ah.c | 16 ++++++++++++++-- sys/netipsec/xform_esp.c | 10 ++++++++-- sys/netipsec/xform_ipcomp.c | 16 ++++++++++++++-- 7 files changed, 68 insertions(+), 15 deletions(-) diff --git a/sys/net/if_ipsec.c b/sys/net/if_ipsec.c index df10af66471c..fd4fb37debfa 100644 --- a/sys/net/if_ipsec.c +++ b/sys/net/if_ipsec.c @@ -450,7 +450,8 @@ ipsec_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, } 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 @@ ipsec_if_input(struct mbuf *m, struct secasvar *sav, uint32_t af) 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 @@ ipsec_if_input(struct mbuf *m, struct secasvar *sav, uint32_t af) } if (sc == NULL) { IPSEC_RUNLOCK(); + ipsec_sahtree_runlock(sahtree_tracker); /* Tunnel was not found. Nothing to do. */ return (0); } @@ -494,6 +499,7 @@ ipsec_if_input(struct mbuf *m, struct secasvar *sav, uint32_t af) 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 @@ ipsec_if_input(struct mbuf *m, struct secasvar *sav, uint32_t af) */ 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 index 44e7d9667d5b..b8969e88abbe 100644 --- a/sys/netipsec/ipsec.h +++ b/sys/netipsec/ipsec.h @@ -330,12 +330,14 @@ VNET_DECLARE(int, natt_cksum_policy); 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 ipsec_setspidx_inpcb(struct inpcb *, struct secpolicyindex *, u_int); 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 index a7410733c43f..0747b88059ab 100644 --- a/sys/netipsec/ipsec6.h +++ b/sys/netipsec/ipsec6.h @@ -60,12 +60,15 @@ VNET_DECLARE(int, ip6_ipsec_ecn); #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 index 221ac879cb18..34767420086a 100644 --- a/sys/netipsec/ipsec_input.c +++ b/sys/netipsec/ipsec_input.c @@ -339,7 +339,7 @@ ipsec4_ctlinput(ipsec_ctlinput_param_t param) */ 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 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, /* 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 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, 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 @@ extern ipproto_input_t *ip6_protox[]; */ 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 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, } /* 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 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, 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 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, 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 index 8f08872eb38a..65c67db983d6 100644 --- a/sys/netipsec/xform_ah.c +++ b/sys/netipsec/xform_ah.c @@ -692,6 +692,7 @@ ah_input_cb(struct cryptop *crp) { 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 @@ ah_input_cb(struct cryptop *crp) 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 @@ ah_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: @@ -823,6 +834,7 @@ ah_input_cb(struct cryptop *crp) 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 index 7aec10549e6c..be8c18da60b3 100644 --- a/sys/netipsec/xform_esp.c +++ b/sys/netipsec/xform_esp.c @@ -492,6 +492,7 @@ static int 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 @@ esp_input_cb(struct cryptop *crp) 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 @@ esp_input_cb(struct cryptop *crp) 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 @@ esp_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: @@ -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 737d4a50098a..778cd955310a 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);