From: claudio Date: Wed, 21 Feb 2024 09:28:29 +0000 (+0000) Subject: Keep mbuf data alignment intact in m_defrag() X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=e78015d9dc23483d48e25ae60e7d5425eb967bf2;p=openbsd Keep mbuf data alignment intact in m_defrag() The recent TSO support in em(4) triggered an alignment error on the TCP header. In em(4) m_defrag() is called before setting up the TSO dma bits and with that the TCP header was suddenly no longer aligned. Like other mbuf functions preserve the data alignment in m_defrag() to prevent such unaligned packets. With help and OK bluhm@ mglocker@ --- diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 5d1f9a7b802..ec675a2333f 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_mbuf.c,v 1.288 2023/10/20 16:25:15 bluhm Exp $ */ +/* $OpenBSD: uipc_mbuf.c,v 1.289 2024/02/21 09:28:29 claudio Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ /* @@ -550,21 +550,24 @@ int m_defrag(struct mbuf *m, int how) { struct mbuf *m0; + unsigned int adj; if (m->m_next == NULL) return (0); KASSERT(m->m_flags & M_PKTHDR); + adj = mtod(m, unsigned long) & (sizeof(long) - 1); if ((m0 = m_gethdr(how, m->m_type)) == NULL) return (ENOBUFS); - if (m->m_pkthdr.len > MHLEN) { - MCLGETL(m0, how, m->m_pkthdr.len); + if (m->m_pkthdr.len + adj > MHLEN) { + MCLGETL(m0, how, m->m_pkthdr.len + adj); if (!(m0->m_flags & M_EXT)) { m_free(m0); return (ENOBUFS); } } + m0->m_data += adj; m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t)); m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len; @@ -583,9 +586,9 @@ m_defrag(struct mbuf *m, int how) memcpy(&m->m_ext, &m0->m_ext, sizeof(struct mbuf_ext)); MCLINITREFERENCE(m); m->m_flags |= m0->m_flags & (M_EXT|M_EXTWR); - m->m_data = m->m_ext.ext_buf; + m->m_data = m->m_ext.ext_buf + adj; } else { - m->m_data = m->m_pktdat; + m->m_data = m->m_pktdat + adj; memcpy(m->m_data, m0->m_data, m0->m_len); } m->m_pkthdr.len = m->m_len = m0->m_len;