Hi, There are more m_pullup()s in IPsec input. Pass down the pointer to the mbuf. At the end it will reach ip_deliver() which expects a pointer to an mbuf anyway.
ok? bluhm Index: netinet/ip_ah.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ah.c,v retrieving revision 1.160 diff -u -p -r1.160 ip_ah.c --- netinet/ip_ah.c 23 Oct 2021 22:19:37 -0000 1.160 +++ netinet/ip_ah.c 23 Oct 2021 23:31:00 -0000 @@ -721,7 +721,7 @@ ah_input(struct mbuf **mp, struct tdb *t /* Release the crypto descriptors */ crypto_freereq(crp); - error = ah_input_cb(tdb, tc, m, clen); + error = ah_input_cb(tdb, tc, mp, clen); if (error) { ipsecstat_inc(ipsec_idrops); tdb->tdb_idrops++; @@ -737,9 +737,10 @@ ah_input(struct mbuf **mp, struct tdb *t } int -ah_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int clen) +ah_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf **mp, int clen) { const struct auth_hash *ahx = tdb->tdb_authalgxform; + struct mbuf *m = *mp; int roff, rplen, skip, protoff; u_int64_t rpl; u_int32_t btsx, esn; @@ -899,10 +900,10 @@ ah_input_cb(struct tdb *tdb, struct tdb_ free(tc, M_XDATA, 0); - return ipsec_common_input_cb(m, tdb, skip, protoff); + return ipsec_common_input_cb(mp, tdb, skip, protoff); baddone: - m_freem(m); + m_freemp(mp); free(tc, M_XDATA, 0); return -1; } Index: netinet/ip_esp.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_esp.c,v retrieving revision 1.179 diff -u -p -r1.179 ip_esp.c --- netinet/ip_esp.c 23 Oct 2021 22:19:37 -0000 1.179 +++ netinet/ip_esp.c 23 Oct 2021 23:43:36 -0000 @@ -546,7 +546,7 @@ esp_input(struct mbuf **mp, struct tdb * /* Release the crypto descriptors */ crypto_freereq(crp); - error = esp_input_cb(tdb, tc, m, clen); + error = esp_input_cb(tdb, tc, mp, clen); if (error) { ipsecstat_inc(ipsec_idrops); tdb->tdb_idrops++; @@ -565,9 +565,10 @@ esp_input(struct mbuf **mp, struct tdb * * ESP input callback, called directly by the crypto driver. */ int -esp_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int clen) +esp_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf **mp, int clen) { u_int8_t lastthree[3], aalg[AH_HMAC_MAX_HASHLEN]; + struct mbuf *m = *mp; int hlen, roff, skip, protoff; struct mbuf *m1, *mo; const struct auth_hash *esph; @@ -751,10 +752,10 @@ esp_input_cb(struct tdb *tdb, struct tdb free(tc, M_XDATA, 0); /* Back to generic IPsec input processing */ - return ipsec_common_input_cb(m, tdb, skip, protoff); + return ipsec_common_input_cb(mp, tdb, skip, protoff); baddone: - m_freem(m); + m_freemp(mp); free(tc, M_XDATA, 0); return -1; } Index: netinet/ip_ipcomp.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipcomp.c,v retrieving revision 1.82 diff -u -p -r1.82 ip_ipcomp.c --- netinet/ip_ipcomp.c 23 Oct 2021 22:19:37 -0000 1.82 +++ netinet/ip_ipcomp.c 23 Oct 2021 23:46:24 -0000 @@ -203,7 +203,7 @@ ipcomp_input(struct mbuf **mp, struct td /* Release the crypto descriptors */ crypto_freereq(crp); - error = ipcomp_input_cb(tdb, tc, m, clen); + error = ipcomp_input_cb(tdb, tc, mp, clen); if (error) { ipsecstat_inc(ipsec_idrops); tdb->tdb_idrops++; @@ -219,8 +219,10 @@ ipcomp_input(struct mbuf **mp, struct td } int -ipcomp_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int clen) +ipcomp_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf **mp, + int clen) { + struct mbuf *m = *mp; int skip, protoff, roff, hlen = IPCOMP_HLENGTH; u_int8_t nproto; u_int64_t ibytes; @@ -259,7 +261,8 @@ ipcomp_input_cb(struct tdb *tdb, struct /* In case it's not done already, adjust the size of the mbuf chain */ m->m_pkthdr.len = clen + hlen + skip; - if ((m->m_len < skip + hlen) && (m = m_pullup(m, skip + hlen)) == 0) { + if (m->m_len < skip + hlen && + (m = *mp = m_pullup(m, skip + hlen)) == NULL) { ipcompstat_inc(ipcomps_hdrops); goto baddone; } @@ -334,10 +337,10 @@ ipcomp_input_cb(struct tdb *tdb, struct m_copyback(m, protoff, sizeof(u_int8_t), &nproto, M_NOWAIT); /* Back to generic IPsec input processing */ - return ipsec_common_input_cb(m, tdb, skip, protoff); + return ipsec_common_input_cb(mp, tdb, skip, protoff); baddone: - m_freem(m); + m_freemp(mp); free(tc, M_XDATA, 0); return -1; } Index: netinet/ip_ipsp.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipsp.h,v retrieving revision 1.212 diff -u -p -r1.212 ip_ipsp.h --- netinet/ip_ipsp.h 23 Oct 2021 22:19:37 -0000 1.212 +++ netinet/ip_ipsp.h 23 Oct 2021 23:32:03 -0000 @@ -571,7 +571,7 @@ int ah_attach(void); int ah_init(struct tdb *, const struct xformsw *, struct ipsecinit *); int ah_zeroize(struct tdb *); int ah_input(struct mbuf **, struct tdb *, int, int); -int ah_input_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int); +int ah_input_cb(struct tdb *, struct tdb_crypto *, struct mbuf **, int); int ah_output(struct mbuf *, struct tdb *, int, int); int ah_output_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int, int); @@ -590,7 +590,7 @@ int esp_attach(void); int esp_init(struct tdb *, const struct xformsw *, struct ipsecinit *); int esp_zeroize(struct tdb *); int esp_input(struct mbuf **, struct tdb *, int, int); -int esp_input_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int); +int esp_input_cb(struct tdb *, struct tdb_crypto *, struct mbuf **, int); int esp_output(struct mbuf *, struct tdb *, int, int); int esp_output_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int, int); @@ -608,7 +608,7 @@ int ipcomp_attach(void); int ipcomp_init(struct tdb *, const struct xformsw *, struct ipsecinit *); int ipcomp_zeroize(struct tdb *); int ipcomp_input(struct mbuf **, struct tdb *, int, int); -int ipcomp_input_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int); +int ipcomp_input_cb(struct tdb *, struct tdb_crypto *, struct mbuf **, int); int ipcomp_output(struct mbuf *, struct tdb *, int, int); int ipcomp_output_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int, int); @@ -648,7 +648,7 @@ void ipsp_init(void); void ipsec_init(void); int ipsec_sysctl(int *, u_int, void *, size_t *, void *, size_t); int ipsec_common_input(struct mbuf **, int, int, int, int, int); -int ipsec_common_input_cb(struct mbuf *, struct tdb *, int, int); +int ipsec_common_input_cb(struct mbuf **, struct tdb *, int, int); int ipsec_delete_policy(struct ipsec_policy *); ssize_t ipsec_hdrsz(struct tdb *); void ipsec_adjust_mtu(struct mbuf *, u_int32_t); Index: netinet/ipsec_input.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ipsec_input.c,v retrieving revision 1.187 diff -u -p -r1.187 ipsec_input.c --- netinet/ipsec_input.c 23 Oct 2021 22:19:37 -0000 1.187 +++ netinet/ipsec_input.c 23 Oct 2021 23:46:35 -0000 @@ -372,8 +372,9 @@ ipsec_common_input(struct mbuf **mp, int * filtering and other sanity checks on the processed packet. */ int -ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff) +ipsec_common_input_cb(struct mbuf **mp, struct tdb *tdbp, int skip, int protoff) { + struct mbuf *m = *mp; int af, sproto; u_int8_t prot; #if NBPFILTER > 0 @@ -396,7 +397,8 @@ ipsec_common_input_cb(struct mbuf *m, st /* Fix IPv4 header */ if (af == AF_INET) { - if ((m->m_len < skip) && ((m = m_pullup(m, skip)) == NULL)) { + if (m->m_len < skip && + (m = *mp = m_pullup(m, skip)) == NULL) { DPRINTF("processing failed for SA %s/%08x", ipsp_address(&tdbp->tdb_dst, buf, sizeof(buf)), ntohl(tdbp->tdb_spi)); @@ -441,7 +443,7 @@ ipsec_common_input_cb(struct mbuf *m, st /* Fix IPv6 header */ if (af == AF_INET6) { if (m->m_len < sizeof(struct ip6_hdr) && - (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { + (m = *mp = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { DPRINTF("processing failed for SA %s/%08x", ipsp_address(&tdbp->tdb_dst, buf, sizeof(buf)), @@ -631,11 +633,11 @@ ipsec_common_input_cb(struct mbuf *m, st } #endif /* Call the appropriate IPsec transform callback. */ - ip_deliver(&m, &skip, prot, af); + ip_deliver(mp, &skip, prot, af); return 0; baddone: - m_freem(m); + m_freemp(mp); return -1; #undef IPSEC_ISTAT }