aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKUROSAWA Takahiro <takahiro.kurosawa@gmail.com>2026-07-15 08:28:00 +0000
committerKristof Provost <kp@FreeBSD.org>2026-07-15 11:44:59 +0000
commitf2202ab5abda7fb09538a1ceda77569b67d83084 (patch)
tree56ae6c43cb5842faf08eff6e8a21013ba5b3e812
parent40c611d0939f187d9a211e9e497291e251deddd3 (diff)
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
-rw-r--r--sys/kern/uipc_mbuf.c12
1 files 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;