On Mon, Oct 28, 2024 at 09:55:53PM +0000, Stuart Henderson wrote:
> On 2024/10/29 00:11, Vitaliy Makkoveev wrote:
> > > - Set up vio(4) interfaces with -tcplro and enable wg(4) interfaces as
> > > usual (In my case, I'm routing IPv4 and IPv6 traffic through wg(4)
> > > tunnel).
> >
> > So, problem lays in vio(4).
>
> Or perhaps that is a trigger but the problem is elsewhere.
>
> bentley@ saw similar wg(4) problems on a machine with just em(4):
>
> em0 at pci0 dev 31 function 6 "Intel I219-V" rev 0x21: msi, address
> 94:c6:91:a3:6d:8a
>
> Now, if I looked at the right files, only ix(4) vm(4) vio(4) have LRO -
> em(4) does not.
>
> We do support TSO on some em(4). Though, while I am not certain, I don't
> think we do on I219-V... Anthony, do you still have that machine available?
> Can you do an "ifconfig em hwfeatures" please so we can be sure?
>
> My best guess from the information I have (I don't think it's possible
> to map from a dmesg attach line to a mac_type without more information -
> the pci id isn't printed) is that it's an em_pch_spt which doesn't do
> TSO...
>
People should try the following diff. It cleans up some of the mbuf
handling and a possible buffer overflow in wg_encap that could be the
cause of the pool corruption.
--
:wq Claudio
Index: net/if_wg.c
===================================================================
RCS file: /cvs/src/sys/net/if_wg.c,v
diff -u -p -r1.38 if_wg.c
--- net/if_wg.c 9 Apr 2024 12:53:08 -0000 1.38
+++ net/if_wg.c 29 Oct 2024 15:46:02 -0000
@@ -860,11 +860,15 @@ wg_send_buf(struct wg_softc *sc, struct
{
struct mbuf *m;
int ret = 0;
+ size_t mlen = len + max_hdr;
retry:
m = m_gethdr(M_WAIT, MT_DATA);
- m->m_len = 0;
- m_copyback(m, 0, len, buf, M_WAIT);
+ if (mlen > MHLEN)
+ MCLGETL(m, M_WAIT, mlen);
+ m_align(m, len);
+ m->m_pkthdr.len = m->m_len = len;
+ memcpy(mtod(m, void *), buf, len);
/* As we're sending a handshake packet here, we want high priority */
m->m_pkthdr.pf.prio = IFQ_MAXPRIO;
@@ -1304,9 +1308,6 @@ wg_send_keepalive(void *_peer)
return;
}
- m->m_len = 0;
- m_calchdrlen(m);
-
t->t_peer = peer;
t->t_mbuf = NULL;
t->t_done = 0;
@@ -1508,9 +1509,10 @@ wg_encap(struct wg_softc *sc, struct mbu
t = wg_tag_get(m);
peer = t->t_peer;
- plaintext_len = min(WG_PKT_WITH_PADDING(m->m_pkthdr.len), t->t_mtu);
+ plaintext_len = WG_PKT_WITH_PADDING(m->m_pkthdr.len);
padding_len = plaintext_len - m->m_pkthdr.len;
- out_len = sizeof(struct wg_pkt_data) + plaintext_len +
NOISE_AUTHTAG_LEN;
+ out_len = sizeof(struct wg_pkt_data) + plaintext_len +
+ NOISE_AUTHTAG_LEN;
/*
* For the time being we allocate a new packet with sufficient size to
@@ -1522,8 +1524,9 @@ wg_encap(struct wg_softc *sc, struct mbu
* noise_remote_encrypt about mbufs, but we would need to sort out the
* p_encap_queue situation first.
*/
- if ((mc = m_clget(NULL, M_NOWAIT, out_len)) == NULL)
+ if ((mc = m_clget(NULL, M_NOWAIT, out_len + max_hdr)) == NULL)
goto error;
+ m_align(mc, out_len);
data = mtod(mc, struct wg_pkt_data *);
m_copydata(m, 0, m->m_pkthdr.len, data->buf);
@@ -1560,8 +1563,7 @@ wg_encap(struct wg_softc *sc, struct mbu
mc->m_pkthdr.ph_loopcnt = m->m_pkthdr.ph_loopcnt;
mc->m_flags &= ~(M_MCAST | M_BCAST);
- mc->m_len = out_len;
- m_calchdrlen(mc);
+ mc->m_pkthdr.len = mc->m_len = out_len;
/*
* We would count ifc_opackets, ifc_obytes of m here, except if_snd