aboutsummaryrefslogtreecommitdiff
path: root/sys/netipsec
diff options
context:
space:
mode:
authorBjoern A. Zeeb <bz@FreeBSD.org>2019-12-01 00:22:04 +0000
committerBjoern A. Zeeb <bz@FreeBSD.org>2019-12-01 00:22:04 +0000
commita4adf6cc653fa8ed9b1d06052f00b2481688d711 (patch)
tree88273d8b1ee747ad53e86d680746812eaaa45ae9 /sys/netipsec
parent1b50b999f9b57eff89002c40559487de9ac43646 (diff)
downloadsrc-a4adf6cc653fa8ed9b1d06052f00b2481688d711.tar.gz
src-a4adf6cc653fa8ed9b1d06052f00b2481688d711.zip
Fix m_pullup() problem after removing PULLDOWN_TESTs and KAME EXT_*macros.
r354748-354750 replaced the KAME macros with m_pulldown() calls. Contrary to the rest of the network stack m_len checks before m_pulldown() were not put in placed (see r354748). Put these m_len checks in place for now (to go along with the style of the network stack since the initial commits). These are not put in for performance but to avoid an error scenario (even though it also will help performance at the moment as it avoid allocating an extra mbuf; not because of the unconditional function call). The observed error case went like this: (1) an mbuf with M_EXT arrives and we call m_pullup() unconditionally on it. (2) m_pullup() will call m_get() unless the requested length is larger than MHLEN (in which case it'll m_freem() the perfectly fine mbuf) and migrate the requested length of data and pkthdr into the new mbuf. (3) If m_get() succeeds, a further m_pullup() call going over MHLEN will fail. This was observed with failing auto-configuration as an RA packet of 200 bytes exceeded MHLEN and the m_pullup() called from nd6_ra_input() dropped the mbuf. (Re-)adding the m_len checks before m_pullup() calls avoids this problems with mbufs using external storage for now. MFC after: 3 weeks Sponsored by: Netflix
Notes
Notes: svn path=/head/; revision=355254
Diffstat (limited to 'sys/netipsec')
-rw-r--r--sys/netipsec/xform_ah.c14
-rw-r--r--sys/netipsec/xform_esp.c14
2 files changed, 16 insertions, 12 deletions
diff --git a/sys/netipsec/xform_ah.c b/sys/netipsec/xform_ah.c
index 2215d4f1c408..2ed9683a0572 100644
--- a/sys/netipsec/xform_ah.c
+++ b/sys/netipsec/xform_ah.c
@@ -575,12 +575,14 @@ ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
/* Figure out header size. */
rplen = HDRSIZE(sav);
- 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;
+ if (m->m_len < skip + rplen) {
+ 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);
diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c
index 918d98b6af22..235d87ae1d98 100644
--- a/sys/netipsec/xform_esp.c
+++ b/sys/netipsec/xform_esp.c
@@ -308,12 +308,14 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
goto bad;
}
- 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;
+ if (m->m_len < skip + sizeof(*esp)) {
+ 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);