The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=f2202ab5abda7fb09538a1ceda77569b67d83084
commit f2202ab5abda7fb09538a1ceda77569b67d83084 Author: KUROSAWA Takahiro <[email protected]> AuthorDate: 2026-07-15 08:28:00 +0000 Commit: Kristof Provost <[email protected]> CommitDate: 2026-07-15 11:44:59 +0000 mbuf: make m_unshare() allow unmapped mbufs m_unshare() had crashed if unmapped mbufs exist in the mbuf chain. This was because memcpy() with mtod() was used without making sure that the mbuf was mapped. Use m_copydata() that cares unmapped mbufs instead. Reviewed by: gallatin Differential Revision: https://reviews.freebsd.org/D58189 --- sys/kern/uipc_mbuf.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index b3632c0bfff6..ffdd115e3e0a 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -2160,7 +2160,8 @@ m_unshare(struct mbuf *m0, int how) * crypto operations, especially when using hardware. */ if ((m->m_flags & M_EXT) == 0) { - if (mprev && (mprev->m_flags & M_EXT) && + if (mprev && + (mprev->m_flags & (M_EXT | M_EXTPG)) == M_EXT && m->m_len <= M_TRAILINGSPACE(mprev)) { /* XXX: this ignores mbuf types */ memcpy(mtod(mprev, caddr_t) + mprev->m_len, @@ -2189,11 +2190,12 @@ m_unshare(struct mbuf *m0, int how) */ KASSERT(m->m_flags & M_EXT, ("m_flags 0x%x", m->m_flags)); /* NB: we only coalesce into a cluster or larger */ - if (mprev != NULL && (mprev->m_flags & M_EXT) && + if (mprev != NULL && + (mprev->m_flags & (M_EXT | M_EXTPG)) == M_EXT && m->m_len <= M_TRAILINGSPACE(mprev)) { /* XXX: this ignores mbuf types */ - memcpy(mtod(mprev, caddr_t) + mprev->m_len, - mtod(m, caddr_t), m->m_len); + m_copydata(m, 0, m->m_len, + mtod(mprev, caddr_t) + mprev->m_len); mprev->m_len += m->m_len; mprev->m_next = m->m_next; /* unlink from chain */ m_free(m); /* reclaim mbuf */ @@ -2224,7 +2226,7 @@ m_unshare(struct mbuf *m0, int how) mlast = NULL; for (;;) { int cc = min(len, MCLBYTES); - memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + off, cc); + m_copydata(m, off, cc, mtod(n, caddr_t)); n->m_len = cc; if (mlast != NULL) mlast->m_next = n;
