freebsd_network: Fix destruction of ref-counted ext_bufs.

The check as to whether or not the buf should be freed was wrong,
leading to incorrect frees.

Fixes double-free KDLs under the idualwifi driver that occur
on boot extremely frequently.

Change-Id: Ia411a6f5c31dd30764705cd87840797f862b4020
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2862
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Augustin Cavalier 2020-06-01 22:40:03 -04:00 committed by waddlesplash
parent 3ac5d98070
commit a68e59dd1d

View File

@ -235,7 +235,6 @@ m_cljget(struct mbuf* memoryBuffer, int how, int size)
static void
mb_free_ext(struct mbuf *memoryBuffer)
{
object_cache *cache = NULL;
volatile u_int *refcnt;
struct mbuf *mref;
int freembuf;
@ -270,22 +269,24 @@ mb_free_ext(struct mbuf *memoryBuffer)
freembuf = 1;
/* Free attached storage only if this mbuf is the only reference to it. */
if (!(*refcnt == 1 || atomic_add(refcnt, -1) == 1)
&& !(freembuf && memoryBuffer != mref))
return;
if (*refcnt == 1 || atomic_add((int32*)refcnt, -1) == 1) {
object_cache *cache = NULL;
if (memoryBuffer->m_ext.ext_type == EXT_CLUSTER)
cache = sChunkCache;
else if (memoryBuffer->m_ext.ext_type == EXT_JUMBO9)
cache = sJumbo9ChunkCache;
else if (memoryBuffer->m_ext.ext_type == EXT_JUMBOP)
cache = sJumboPageSizeCache;
else
panic("unknown mbuf ext_type %d", memoryBuffer->m_ext.ext_type);
if (memoryBuffer->m_ext.ext_type == EXT_CLUSTER)
cache = sChunkCache;
else if (memoryBuffer->m_ext.ext_type == EXT_JUMBO9)
cache = sJumbo9ChunkCache;
else if (memoryBuffer->m_ext.ext_type == EXT_JUMBOP)
cache = sJumboPageSizeCache;
else
panic("unknown mbuf ext_type %d", memoryBuffer->m_ext.ext_type);
object_cache_free(cache, memoryBuffer->m_ext.ext_buf, 0);
memoryBuffer->m_ext.ext_buf = NULL;
object_cache_free(sMBufCache, memoryBuffer, 0);
object_cache_free(cache, memoryBuffer->m_ext.ext_buf, 0);
object_cache_free(sMBufCache, mref, 0);
}
if (freembuf && memoryBuffer != mref)
object_cache_free(sMBufCache, memoryBuffer, 0);
}