UMA mbuf allocator use after free detection

Mike Silbersack silby at silby.com
Wed Jun 15 07:49:25 GMT 2005


The attached patch uses the trash ctor/dtor routines from uma_dbg to help 
detect use after free conditions for mbufs, and mbuf clusters.  It doesn't 
seem to cause any unexpected problems with xl, ath, or wi, but it does 
cause issues with iwi.  That is good, because iwi has some problems that 
need to be resolved.

I'd appreciate it if people could apply the patch and see if it causes any 
panics or unexpected behavior on their systems.  If all mbuf usage is 
correct, there should be no visible effect.

This code is of course only active when you have INVARIANTS compiled in so 
that it does not slow down performance otherwise.

Thanks,

Mike "Silby" Silbersack
-------------- next part --------------
diff -u -r /usr/src/sys.old/kern/kern_mbuf.c /usr/src/sys/kern/kern_mbuf.c
--- /usr/src/sys.old/kern/kern_mbuf.c	Sun Jun 12 19:43:12 2005
+++ /usr/src/sys/kern/kern_mbuf.c	Wed Jun 15 02:26:45 2005
@@ -46,6 +46,8 @@
 #include <vm/vm.h>
 #include <vm/vm_page.h>
 #include <vm/uma.h>
+#include <vm/uma_int.h>
+#include <vm/uma_dbg.h>
 
 /*
  * In FreeBSD, Mbufs and Mbuf Clusters are allocated from UMA
@@ -134,9 +136,17 @@
 	 * Configure UMA zones for Mbufs, Clusters, and Packets.
 	 */
 	zone_mbuf = uma_zcreate("Mbuf", MSIZE, mb_ctor_mbuf, mb_dtor_mbuf,
+#ifdef INVARIANTS
+	    trash_init, trash_fini, MSIZE - 1, UMA_ZONE_MAXBUCKET);
+#else
 	    NULL, NULL, MSIZE - 1, UMA_ZONE_MAXBUCKET);
+#endif
 	zone_clust = uma_zcreate("MbufClust", MCLBYTES, mb_ctor_clust,
+#ifdef INVARIANTS
+	    mb_dtor_clust, trash_init, trash_fini, UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
+#else
 	    mb_dtor_clust, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
+#endif
 	if (nmbclusters > 0)
 		uma_zone_set_max(zone_clust, nmbclusters);
 	zone_pack = uma_zsecond_create("Packet", mb_ctor_pack, mb_dtor_pack,
@@ -190,6 +200,9 @@
 	int flags;
 	short type;
 
+#ifdef INVARIANTS
+	trash_ctor(mem, size, arg, how);
+#endif
 	m = (struct mbuf *)mem;
 	args = (struct mb_args *)arg;
 	flags = args->flags;
@@ -227,6 +240,9 @@
 	m = (struct mbuf *)mem;
 	if ((m->m_flags & M_PKTHDR) != 0)
 		m_tag_delete_chain(m, NULL);
+#ifdef INVARIANTS
+	trash_dtor(mem, size, arg);
+#endif
 	mbstat.m_mbufs -= 1;	/* XXX */
 }
 
@@ -239,6 +255,9 @@
 	m = (struct mbuf *)mem;
 	if ((m->m_flags & M_PKTHDR) != 0)
 		m_tag_delete_chain(m, NULL);
+#ifdef INVARIANTS
+	trash_dtor(m->m_ext.ext_buf, MCLBYTES, arg);
+#endif
 	mbstat.m_mbufs -= 1;	/* XXX */
 	mbstat.m_mclusts -= 1;	/* XXX */
 }
@@ -254,6 +273,9 @@
 {
 	struct mbuf *m;
 
+#ifdef INVARIANTS
+	trash_ctor(mem, size, arg, how);
+#endif
 	m = (struct mbuf *)arg;
 	m->m_ext.ext_buf = (caddr_t)mem;
 	m->m_data = m->m_ext.ext_buf;
@@ -271,6 +293,9 @@
 static void
 mb_dtor_clust(void *mem, int size, void *arg)
 {
+#ifdef INVARIANTS
+	trash_dtor(mem, size, arg);
+#endif
 	mbstat.m_mclusts -= 1;	/* XXX */
 }
 
@@ -288,6 +313,9 @@
 	uma_zalloc_arg(zone_clust, m, how);
 	if (m->m_ext.ext_buf == NULL)
 		return (ENOMEM);
+#ifdef INVARIANTS
+	trash_init(m->m_ext.ext_buf, MCLBYTES, how);
+#endif
 	mbstat.m_mclusts -= 1;	/* XXX */
 	return (0);
 }
@@ -302,6 +330,9 @@
 	struct mbuf *m;
 
 	m = (struct mbuf *)mem;
+#ifdef INVARIANTS
+	trash_fini(m->m_ext.ext_buf, MCLBYTES);
+#endif
 	uma_zfree_arg(zone_clust, m->m_ext.ext_buf, NULL);
 	m->m_ext.ext_buf = NULL;
 	mbstat.m_mclusts += 1;	/* XXX */
@@ -326,6 +357,9 @@
 	flags = args->flags;
 	type = args->type;
 
+#ifdef INVARIANTS
+	trash_ctor(m->m_ext.ext_buf, MCLBYTES, arg, how);
+#endif
 	m->m_type = type;
 	m->m_next = NULL;
 	m->m_nextpkt = NULL;


More information about the freebsd-current mailing list