diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-03-23 10:47:15 -0600 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-03-23 11:51:00 -0600 |
commit | dfb1aa325179d3263518574fc64f962476021b92 (patch) | |
tree | 78a6944a11f1eb74379e6e0d669a47ad110f7903 | |
parent | if_wg: implement selection of FIB (routing table) for tunneled packets (diff) | |
download | wireguard-freebsd-dfb1aa325179d3263518574fc64f962476021b92.tar.xz wireguard-freebsd-dfb1aa325179d3263518574fc64f962476021b92.zip |
if_wg: fix decryption failures on jumbo ingress
All of this allocation_order and copying garbage needs to go away by
making the crypto take scatter gather lists.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r-- | src/if_wg.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/src/if_wg.c b/src/if_wg.c index 020e595..9de10e8 100644 --- a/src/if_wg.c +++ b/src/if_wg.c @@ -2356,14 +2356,37 @@ wg_input(struct mbuf *m0, int offset, struct inpcb *inpcb, /* * Ensure mbuf has at least enough contiguous data to peel off our - * headers at the beginning. + * headers at the beginning, and make a jumbo contigious copy if we've + * got a jumbo frame. This is pretty sloppy, and we should just fix the + * crypto routines to deal with mbuf clusters instead. */ - if ((m = m_defrag(m0, M_NOWAIT)) == NULL) { + if (!m0->m_next) + m = m0; + else { + int allocation_order; + + if (m0->m_pkthdr.len <= MCLBYTES) + allocation_order = MCLBYTES; + else if (m0->m_pkthdr.len <= MJUMPAGESIZE) + allocation_order = MJUMPAGESIZE; + else if (m0->m_pkthdr.len <= MJUM9BYTES) + allocation_order = MJUM9BYTES; + else if (m0->m_pkthdr.len <= MJUM16BYTES) + allocation_order = MJUM16BYTES; + else { + m_freem(m0); + return; + } + if ((m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, allocation_order)) == NULL) { + m_freem(m0); + return; + } + m->m_len = m->m_pkthdr.len = m0->m_pkthdr.len; + m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, void *)); m_freem(m0); - return; } data = mtod(m, void *); - pkttype = *(uint32_t*)data; + pkttype = *(uint32_t *)data; t = wg_tag_get(m); if (t == NULL) { goto free; @@ -2390,7 +2413,6 @@ wg_input(struct mbuf *m0, int offset, struct inpcb *inpcb, } } else if (pktlen >= sizeof(struct wg_pkt_data) + NOISE_AUTHTAG_LEN && pkttype == WG_PKT_DATA) { - pkt_data = data; remote = wg_index_get(sc, pkt_data->r_idx); if (remote == NULL) { |