netinet*: replace IP6_EXTHDR_GET()

In a few places we have IP6_EXTHDR_GET() left in upper layer protocols.
The IP6_EXTHDR_GET() macro might perform an m_pulldown() in case the data
fragment is not contiguous.

Convert these last remaining instances into m_pullup()s instead.
In CARP, for example, we will a few lines later call m_pullup() anyway,
the IPsec code coming from OpenBSD would otherwise have done the m_pullup()
and are copying the data a bit later anyway, so pulling it in seems no
better or worse.

Note: this leaves very few m_pulldown() cases behind in the tree and we
might want to consider removing them as well to make mbuf management
easier again on a path to variable size mbufs, especially given
m_pulldown() still has an issue not re-checking M_WRITEABLE().

Reviewed by:	gallatin
MFC after:	8 weeks
Sponsored by:	Netflix
Differential Revision:	https://reviews.freebsd.org/D22335
This commit is contained in:
Bjoern A. Zeeb 2019-11-15 21:44:17 +00:00
parent a61b5cfbbf
commit 63abacc204
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=354749
4 changed files with 19 additions and 11 deletions

View File

@ -567,12 +567,13 @@ carp6_input(struct mbuf **mp, int *offp, int proto)
/* verify that we have a complete carp packet */ /* verify that we have a complete carp packet */
len = m->m_len; len = m->m_len;
IP6_EXTHDR_GET(ch, struct carp_header *, m, *offp, sizeof(*ch)); m = m_pullup(m, *offp + sizeof(*ch));
if (ch == NULL) { if (m == NULL) {
CARPSTATS_INC(carps_badlen); CARPSTATS_INC(carps_badlen);
CARP_DEBUG("%s: packet size %u too small\n", __func__, len); CARP_DEBUG("%s: packet size %u too small\n", __func__, len);
return (IPPROTO_DONE); return (IPPROTO_DONE);
} }
ch = (struct carp_header *)(mtod(m, caddr_t) + *offp);
/* verify the CARP checksum */ /* verify the CARP checksum */

View File

@ -103,13 +103,13 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
SCTP_STAT_INCR_COUNTER64(sctps_inpackets); SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
/* Get IP, SCTP, and first chunk header together in the first mbuf. */ /* Get IP, SCTP, and first chunk header together in the first mbuf. */
offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
ip6 = mtod(m, struct ip6_hdr *); m = m_pullup(m, offset);
IP6_EXTHDR_GET(sh, struct sctphdr *, m, iphlen, if (m == NULL) {
(int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)));
if (sh == NULL) {
SCTP_STAT_INCR(sctps_hdrops); SCTP_STAT_INCR(sctps_hdrops);
return (IPPROTO_DONE); return (IPPROTO_DONE);
} }
ip6 = mtod(m, struct ip6_hdr *);
sh = (struct sctphdr *)(mtod(m, caddr_t) + iphlen);
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
offset -= sizeof(struct sctp_chunkhdr); offset -= sizeof(struct sctp_chunkhdr);
memset(&src, 0, sizeof(struct sockaddr_in6)); memset(&src, 0, sizeof(struct sockaddr_in6));

View File

@ -575,14 +575,14 @@ ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
/* Figure out header size. */ /* Figure out header size. */
rplen = HDRSIZE(sav); rplen = HDRSIZE(sav);
/* XXX don't pullup, just copy header */ m = m_pullup(m, skip + rplen);
IP6_EXTHDR_GET(ah, struct newah *, m, skip, rplen); if (m == NULL) {
if (ah == NULL) {
DPRINTF(("ah_input: cannot pullup header\n")); DPRINTF(("ah_input: cannot pullup header\n"));
AHSTAT_INC(ahs_hdrops); /*XXX*/ AHSTAT_INC(ahs_hdrops); /*XXX*/
error = ENOBUFS; error = ENOBUFS;
goto bad; goto bad;
} }
ah = (struct newah *)(mtod(m, caddr_t) + skip);
/* Check replay window, if applicable. */ /* Check replay window, if applicable. */
SECASVAR_LOCK(sav); SECASVAR_LOCK(sav);

View File

@ -307,8 +307,15 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
ESPSTAT_INC(esps_badilen); ESPSTAT_INC(esps_badilen);
goto bad; goto bad;
} }
/* XXX don't pullup, just copy header */
IP6_EXTHDR_GET(esp, struct newesp *, m, skip, sizeof (struct newesp)); m = m_pullup(m, skip + sizeof(*esp));
if (m == NULL) {
DPRINTF(("%s: cannot pullup header\n", __func__));
ESPSTAT_INC(esps_hdrops); /*XXX*/
error = ENOBUFS;
goto bad;
}
esp = (struct newesp *)(mtod(m, caddr_t) + skip);
esph = sav->tdb_authalgxform; esph = sav->tdb_authalgxform;
espx = sav->tdb_encalgxform; espx = sav->tdb_encalgxform;