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 <[email protected]>
This commit is contained in:
Augustin Cavalier
2020-06-02 03:13:59 +00:00
committed by waddlesplash
parent 3ac5d98070
commit a68e59dd1d
+6 -5
View File
@@ -235,7 +235,6 @@ m_cljget(struct mbuf* memoryBuffer, int how, int size)
static void static void
mb_free_ext(struct mbuf *memoryBuffer) mb_free_ext(struct mbuf *memoryBuffer)
{ {
object_cache *cache = NULL;
volatile u_int *refcnt; volatile u_int *refcnt;
struct mbuf *mref; struct mbuf *mref;
int freembuf; int freembuf;
@@ -270,9 +269,8 @@ mb_free_ext(struct mbuf *memoryBuffer)
freembuf = 1; freembuf = 1;
/* Free attached storage only if this mbuf is the only reference to it. */ /* Free attached storage only if this mbuf is the only reference to it. */
if (!(*refcnt == 1 || atomic_add(refcnt, -1) == 1) if (*refcnt == 1 || atomic_add((int32*)refcnt, -1) == 1) {
&& !(freembuf && memoryBuffer != mref)) object_cache *cache = NULL;
return;
if (memoryBuffer->m_ext.ext_type == EXT_CLUSTER) if (memoryBuffer->m_ext.ext_type == EXT_CLUSTER)
cache = sChunkCache; cache = sChunkCache;
@@ -284,7 +282,10 @@ mb_free_ext(struct mbuf *memoryBuffer)
panic("unknown mbuf ext_type %d", memoryBuffer->m_ext.ext_type); panic("unknown mbuf ext_type %d", memoryBuffer->m_ext.ext_type);
object_cache_free(cache, memoryBuffer->m_ext.ext_buf, 0); object_cache_free(cache, memoryBuffer->m_ext.ext_buf, 0);
memoryBuffer->m_ext.ext_buf = NULL; object_cache_free(sMBufCache, mref, 0);
}
if (freembuf && memoryBuffer != mref)
object_cache_free(sMBufCache, memoryBuffer, 0); object_cache_free(sMBufCache, memoryBuffer, 0);
} }