From 48d183faca1a4eab786d57c494f6a063ef95d1d2 Mon Sep 17 00:00:00 2001 From: Archie Cobbs Date: Fri, 31 May 2002 22:09:57 +0000 Subject: [PATCH] Fix a bug in m_split(): the "m->m_ext.ext_size" field of an mbuf was being set to zero. This field indicates the total space in the external buffer and therefore should not be modified after the external buffer is added. Add a comment warning that the mbufs returned by m_split() might be read-only. Fix M_TRAILINGSPACE() to return zero if !M_WRITABLE(m). Reviewed by: freebsd-net Obtained from: Vernier Networks, Inc. MFC after: 1 week --- sys/kern/uipc_mbuf.c | 6 +++++- sys/sys/mbuf.h | 11 +++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 80c40611203..27ca156c23c 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -560,6 +560,11 @@ bad: * Partition an mbuf chain in two pieces, returning the tail -- * all but the first len0 bytes. In case of failure, it returns NULL and * attempts to restore the chain to its original state. + * + * Note that the resulting mbufs might be read-only, because the new + * mbuf can end up sharing an mbuf cluster with the original mbuf if + * the "breaking point" happens to lie within a cluster mbuf. Use the + * M_WRITABLE() macro to check for this case. */ struct mbuf * m_split(struct mbuf *m0, int len0, int wait) @@ -609,7 +614,6 @@ extpacket: n->m_flags |= M_EXT; n->m_ext = m->m_ext; MEXT_ADD_REF(m); - m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */ n->m_data = m->m_data + len; } else { bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain); diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 4075a5d2265..5cfb1aebf35 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -344,6 +344,9 @@ struct mbstat { /* * Compute the amount of space available * before the current start of data in an mbuf. + * + * The M_WRITABLE() is a temporary, conservative safety measure: the burden + * of checking writability of the mbuf data area rests solely with the caller. */ #define M_LEADINGSPACE(m) \ ((m)->m_flags & M_EXT ? \ @@ -354,10 +357,14 @@ struct mbstat { /* * Compute the amount of space available * after the end of data in an mbuf. + * + * The M_WRITABLE() is a temporary, conservative safety measure: the burden + * of checking writability of the mbuf data area rests solely with the caller. */ #define M_TRAILINGSPACE(m) \ - ((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf + \ - (m)->m_ext.ext_size - ((m)->m_data + (m)->m_len) : \ + ((m)->m_flags & M_EXT ? \ + (M_WRITABLE(m) ? (m)->m_ext.ext_buf + (m)->m_ext.ext_size \ + - ((m)->m_data + (m)->m_len) : 0) : \ &(m)->m_dat[MLEN] - ((m)->m_data + (m)->m_len)) /*