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:
bz 2019-11-15 21:44:17 +00:00
parent 667b9bd5d8
commit 1feeff48a5
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 */
len = m->m_len;
IP6_EXTHDR_GET(ch, struct carp_header *, m, *offp, sizeof(*ch));
if (ch == NULL) {
m = m_pullup(m, *offp + sizeof(*ch));
if (m == NULL) {
CARPSTATS_INC(carps_badlen);
CARP_DEBUG("%s: packet size %u too small\n", __func__, len);
return (IPPROTO_DONE);
}
ch = (struct carp_header *)(mtod(m, caddr_t) + *offp);
/* 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);
/* Get IP, SCTP, and first chunk header together in the first mbuf. */
offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
ip6 = mtod(m, struct ip6_hdr *);
IP6_EXTHDR_GET(sh, struct sctphdr *, m, iphlen,
(int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)));
if (sh == NULL) {
m = m_pullup(m, offset);
if (m == NULL) {
SCTP_STAT_INCR(sctps_hdrops);
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));
offset -= sizeof(struct sctp_chunkhdr);
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. */
rplen = HDRSIZE(sav);
/* XXX don't pullup, just copy header */
IP6_EXTHDR_GET(ah, struct newah *, m, skip, rplen);
if (ah == NULL) {
m = m_pullup(m, skip + rplen);
if (m == NULL) {
DPRINTF(("ah_input: cannot pullup header\n"));
AHSTAT_INC(ahs_hdrops); /*XXX*/
error = ENOBUFS;
goto bad;
}
ah = (struct newah *)(mtod(m, caddr_t) + skip);
/* Check replay window, if applicable. */
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);
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;
espx = sav->tdb_encalgxform;