aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-03-23 10:47:15 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2021-03-23 11:51:00 -0600
commitdfb1aa325179d3263518574fc64f962476021b92 (patch)
tree78a6944a11f1eb74379e6e0d669a47ad110f7903
parentif_wg: implement selection of FIB (routing table) for tunneled packets (diff)
downloadwireguard-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.c32
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) {