From bec0ed23d13fd98966ae8ddab555e0b00e36cf46 Mon Sep 17 00:00:00 2001 From: bluhm Date: Thu, 11 Nov 2021 18:08:17 +0000 Subject: [PATCH] Do not call ip_deliver() recursively from IPsec. As there is no crypto task anymore, it is possible to return the next protocol. Then ip_deliver() will walk the header chain in its loop. IPsec bridge(4) tested by jan@ OK mvs@ tobhe@ jan@ --- sys/net/if_bridge.c | 9 ++++++--- sys/netinet/ip_ah.c | 19 ++----------------- sys/netinet/ip_esp.c | 20 ++------------------ sys/netinet/ip_ipcomp.c | 8 ++------ sys/netinet/ipsec_input.c | 39 +++++++++++++-------------------------- sys/netinet/tcp_subr.c | 4 ++-- sys/netinet/udp_usrreq.c | 5 ++--- 7 files changed, 29 insertions(+), 75 deletions(-) diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index cd9b0fa9a5a..ceb93e70149 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.357 2021/10/23 22:19:37 bluhm Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.358 2021/11/11 18:08:17 bluhm Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -1487,7 +1487,7 @@ bridge_ipsec(struct ifnet *ifp, struct ether_header *eh, int hassnap, struct tdb *tdb; u_int32_t spi; u_int16_t cpi; - int error, off; + int error, off, prot; u_int8_t proto = 0; struct ip *ip; #ifdef INET6 @@ -1575,7 +1575,10 @@ bridge_ipsec(struct ifnet *ifp, struct ether_header *eh, int hassnap, tdb->tdb_soft_first_use); } - (*(tdb->tdb_xform->xf_input))(&m, tdb, hlen, off); + prot = (*(tdb->tdb_xform->xf_input))(&m, tdb, hlen, + off); + if (prot != IPPROTO_DONE) + ip_deliver(&m, &hlen, prot, af); return (1); } else { skiplookup: diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c index 140065807c4..fc423f62982 100644 --- a/sys/netinet/ip_ah.c +++ b/sys/netinet/ip_ah.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ah.c,v 1.165 2021/10/25 09:47:02 tobhe Exp $ */ +/* $OpenBSD: ip_ah.c,v 1.166 2021/11/11 18:08:18 bluhm Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -563,21 +563,18 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_wrap); - error = ENOBUFS; goto drop; case 2: DPRINTF("old packet received in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_replay); - error = ENOBUFS; goto drop; case 3: DPRINTF("duplicate packet received in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_replay); - error = ENOBUFS; goto drop; default: DPRINTF("bogus value from checkreplaywindow() " @@ -585,7 +582,6 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_replay); - error = ENOBUFS; goto drop; } } @@ -597,7 +593,6 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_badauthl); - error = EACCES; goto drop; } if (skip + ahx->authsize + rplen > m->m_pkthdr.len) { @@ -607,7 +602,6 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_badauthl); - error = EACCES; goto drop; } @@ -622,7 +616,6 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); tdb_delete(tdb); - error = ENXIO; goto drop; } @@ -638,7 +631,6 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) if (crp == NULL) { DPRINTF("failed to acquire crypto descriptors"); ahstat_inc(ahs_crypto); - error = ENOBUFS; goto drop; } @@ -664,7 +656,6 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) if (ptr == NULL) { DPRINTF("failed to allocate buffer"); ahstat_inc(ahs_crypto); - error = ENOBUFS; goto drop; } @@ -720,7 +711,6 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_badauth); - error = -1; goto drop; } @@ -750,21 +740,18 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_wrap); - error = -1; goto drop; case 2: DPRINTF("old packet received in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_replay); - error = -1; goto drop; case 3: DPRINTF("duplicate packet received in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_replay); - error = -1; goto drop; default: DPRINTF("bogus value from checkreplaywindow() " @@ -772,7 +759,6 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_replay); - error = -1; goto drop; } } @@ -784,7 +770,6 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_hdrops); - error = -1; goto drop; } @@ -863,7 +848,7 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) free(ptr, M_XDATA, 0); m_freemp(mp); crypto_freereq(crp); - return error; + return IPPROTO_DONE; } /* diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c index 8a7089e911e..0c3bbc757c2 100644 --- a/sys/netinet/ip_esp.c +++ b/sys/netinet/ip_esp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp.c,v 1.186 2021/11/08 22:36:18 tobhe Exp $ */ +/* $OpenBSD: ip_esp.c,v 1.187 2021/11/11 18:08:18 bluhm Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -362,7 +362,6 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) if (plen <= 0) { DPRINTF("invalid payload length"); espstat_inc(esps_badilen); - error = EINVAL; goto drop; } @@ -378,7 +377,6 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_badilen); - error = EINVAL; goto drop; } } @@ -397,21 +395,18 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_wrap); - error = EACCES; goto drop; case 2: DPRINTF("old packet received in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_replay); - error = EACCES; goto drop; case 3: DPRINTF("duplicate packet received in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_replay); - error = EACCES; goto drop; default: DPRINTF("bogus value from checkreplaywindow() " @@ -419,7 +414,6 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_replay); - error = EACCES; goto drop; } } @@ -434,7 +428,6 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); tdb_delete(tdb); - error = ENXIO; goto drop; } @@ -450,7 +443,6 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) if (crp == NULL) { DPRINTF("failed to acquire crypto descriptors"); espstat_inc(esps_crypto); - error = ENOBUFS; goto drop; } @@ -537,7 +529,6 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_badauth); - error = -1; goto drop; } @@ -563,21 +554,18 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_wrap); - error = -1; goto drop; case 2: DPRINTF("old packet received in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_replay); - error = -1; goto drop; case 3: DPRINTF("duplicate packet received in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_replay); - error = -1; goto drop; default: DPRINTF("bogus value from checkreplaywindow() " @@ -585,7 +573,6 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_replay); - error = -1; goto drop; } } @@ -597,7 +584,6 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_hdrops); - error = -1; goto drop; } @@ -668,7 +654,6 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_badilen); - error = -1; goto drop; } @@ -678,7 +663,6 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); espstat_inc(esps_badenc); - error = -1; goto drop; } @@ -694,7 +678,7 @@ esp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) drop: m_freemp(mp); crypto_freereq(crp); - return error; + return IPPROTO_DONE; } /* diff --git a/sys/netinet/ip_ipcomp.c b/sys/netinet/ip_ipcomp.c index 6e381a0a830..be1a3931ee9 100644 --- a/sys/netinet/ip_ipcomp.c +++ b/sys/netinet/ip_ipcomp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipcomp.c,v 1.86 2021/10/24 18:15:58 tobhe Exp $ */ +/* $OpenBSD: ip_ipcomp.c,v 1.87 2021/11/11 18:08:18 bluhm Exp $ */ /* * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org) @@ -154,7 +154,6 @@ ipcomp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) if (crp == NULL) { DPRINTF("failed to acquire crypto descriptors"); ipcompstat_inc(ipcomps_crypto); - error = ENOBUFS; goto drop; } crdc = &crp->crp_desc[0]; @@ -202,7 +201,6 @@ ipcomp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) { pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD); tdb_delete(tdb); - error = -1; goto drop; } /* Notify on soft expiration */ @@ -218,7 +216,6 @@ ipcomp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) if (m->m_len < skip + hlen && (m = *mp = m_pullup(m, skip + hlen)) == NULL) { ipcompstat_inc(ipcomps_hdrops); - error = -1; goto drop; } @@ -229,7 +226,6 @@ ipcomp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ipcompstat_inc(ipcomps_hdrops); - error = -1; goto drop; } /* Keep the next protocol field */ @@ -295,7 +291,7 @@ ipcomp_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) drop: m_freemp(mp); crypto_freereq(crp); - return error; + return IPPROTO_DONE; } /* diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c index 6f575d4f279..b1465f43b8c 100644 --- a/sys/netinet/ipsec_input.c +++ b/sys/netinet/ipsec_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsec_input.c,v 1.190 2021/11/01 09:19:10 bluhm Exp $ */ +/* $OpenBSD: ipsec_input.c,v 1.191 2021/11/11 18:08:18 bluhm Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -194,7 +194,7 @@ ipsec_common_input(struct mbuf **mp, int skip, int protoff, int af, int sproto, struct ifnet *encif; u_int32_t spi; u_int16_t cpi; - int error; + int prot; #ifdef ENCDEBUG char buf[INET6_ADDRSTRLEN]; #endif @@ -207,14 +207,12 @@ ipsec_common_input(struct mbuf **mp, int skip, int protoff, int af, int sproto, if ((sproto == IPPROTO_IPCOMP) && (m->m_flags & M_COMP)) { DPRINTF("repeated decompression"); ipcompstat_inc(ipcomps_pdrops); - error = EINVAL; goto drop; } if (m->m_pkthdr.len - skip < 2 * sizeof(u_int32_t)) { DPRINTF("packet too small"); IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops); - error = EINVAL; goto drop; } @@ -268,7 +266,6 @@ ipsec_common_input(struct mbuf **mp, int skip, int protoff, int af, int sproto, default: DPRINTF("unsupported protocol family %d", af); IPSEC_ISTAT(esps_nopf, ahs_nopf, ipcomps_nopf); - error = EPFNOSUPPORT; goto drop; } @@ -278,7 +275,6 @@ ipsec_common_input(struct mbuf **mp, int skip, int protoff, int af, int sproto, DPRINTF("could not find SA for packet to %s, spi %08x", ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi)); IPSEC_ISTAT(esps_notdb, ahs_notdb, ipcomps_notdb); - error = ENOENT; goto drop; } @@ -287,7 +283,6 @@ ipsec_common_input(struct mbuf **mp, int skip, int protoff, int af, int sproto, ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi), tdbp->tdb_sproto); IPSEC_ISTAT(esps_invalid, ahs_invalid, ipcomps_invalid); - error = EINVAL; goto drop; } @@ -296,7 +291,6 @@ ipsec_common_input(struct mbuf **mp, int skip, int protoff, int af, int sproto, ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi), tdbp->tdb_sproto); espstat_inc(esps_udpinval); - error = EINVAL; goto drop; } @@ -305,7 +299,6 @@ ipsec_common_input(struct mbuf **mp, int skip, int protoff, int af, int sproto, ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi), tdbp->tdb_sproto); espstat_inc(esps_udpneeded); - error = EINVAL; goto drop; } @@ -314,7 +307,6 @@ ipsec_common_input(struct mbuf **mp, int skip, int protoff, int af, int sproto, ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi), tdbp->tdb_sproto); IPSEC_ISTAT(esps_noxform, ahs_noxform, ipcomps_noxform); - error = ENXIO; goto drop; } @@ -326,7 +318,6 @@ ipsec_common_input(struct mbuf **mp, int skip, int protoff, int af, int sproto, ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi), tdbp->tdb_sproto); IPSEC_ISTAT(esps_pdrops, ahs_pdrops, ipcomps_pdrops); - error = EACCES; goto drop; } @@ -352,19 +343,19 @@ ipsec_common_input(struct mbuf **mp, int skip, int protoff, int af, int sproto, * Call appropriate transform and return -- callback takes care of * everything else. */ - error = (*(tdbp->tdb_xform->xf_input))(mp, tdbp, skip, protoff); - if (error) { + prot = (*(tdbp->tdb_xform->xf_input))(mp, tdbp, skip, protoff); + if (prot == IPPROTO_DONE) { ipsecstat_inc(ipsec_idrops); tdbp->tdb_idrops++; } - return error; + return prot; drop: m_freemp(mp); ipsecstat_inc(ipsec_idrops); if (tdbp != NULL) tdbp->tdb_idrops++; - return error; + return IPPROTO_DONE; } /* @@ -630,16 +621,15 @@ ipsec_common_input_cb(struct mbuf **mp, struct tdb *tdbp, int skip, int protoff) m = *mp; if_put(ifp); if (m == NULL) - return 0; + return IPPROTO_DONE; } #endif - /* Call the appropriate IPsec transform callback. */ - ip_deliver(mp, &skip, prot, af); - return 0; + /* Return to the appropriate protocol handler in deliver loop. */ + return prot; baddone: m_freemp(mp); - return -1; + return IPPROTO_DONE; #undef IPSEC_ISTAT } @@ -829,8 +819,7 @@ ah46_input(struct mbuf **mp, int *offp, int proto, int af) return IPPROTO_DONE; } - ipsec_common_input(mp, *offp, protoff, af, proto, 0); - return IPPROTO_DONE; + return ipsec_common_input(mp, *offp, protoff, af, proto, 0); } void @@ -863,8 +852,7 @@ esp46_input(struct mbuf **mp, int *offp, int proto, int af) return IPPROTO_DONE; } - ipsec_common_input(mp, *offp, protoff, af, proto, 0); - return IPPROTO_DONE; + return ipsec_common_input(mp, *offp, protoff, af, proto, 0); } /* IPv4 IPCOMP wrapper */ @@ -888,8 +876,7 @@ ipcomp46_input(struct mbuf **mp, int *offp, int proto, int af) return IPPROTO_DONE; } - ipsec_common_input(mp, *offp, protoff, af, proto, 0); - return IPPROTO_DONE; + return ipsec_common_input(mp, *offp, protoff, af, proto, 0); } void diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index c1349d84397..1597852ae25 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_subr.c,v 1.181 2021/10/23 22:19:37 bluhm Exp $ */ +/* $OpenBSD: tcp_subr.c,v 1.182 2021/11/11 18:08:18 bluhm Exp $ */ /* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */ /* @@ -964,7 +964,7 @@ tcp_signature_tdb_input(struct mbuf **mp, struct tdb *tdbp, int skip, int protoff) { m_freemp(mp); - return (EINVAL); + return (IPPROTO_DONE); } int diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index e49cc2fa891..098ee1401b9 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.263 2021/10/23 22:19:37 bluhm Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.264 2021/11/11 18:08:18 bluhm Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -305,9 +305,8 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af) espstat_inc(esps_udpencin); protoff = af == AF_INET ? offsetof(struct ip, ip_p) : offsetof(struct ip6_hdr, ip6_nxt); - ipsec_common_input(mp, skip, protoff, + return ipsec_common_input(mp, skip, protoff, af, IPPROTO_ESP, 1); - return IPPROTO_DONE; } } #endif -- 2.20.1