Mbuf double-free guilty party detection patch

Mike Silbersack silby at silby.com
Sat Jun 25 22:13:37 GMT 2005


Here's a fixed version of the patch that should return the correct 
address.  I made two mistakes in the version I posted last night; that's 
what I get for testing, then making a few changes "that should work."

I changed this version so that it doesn't panic, but continues on when it 
discovers the reuse of the mbuf.  I figure this will make debugging less 
painful for everyone. :)

Mike "Silby" Silbersack
-------------- next part --------------
diff -u -r /usr/src/sys.old/kern/uipc_mbuf.c /usr/src/sys/kern/uipc_mbuf.c
--- /usr/src/sys.old/kern/uipc_mbuf.c	Fri Jun 24 20:13:59 2005
+++ /usr/src/sys/kern/uipc_mbuf.c	Fri Jun 24 20:50:16 2005
@@ -219,7 +219,7 @@
  * storage attached to them if the reference count hits 0.
  */
 void
-mb_free_ext(struct mbuf *m)
+mb_free_ext(struct mbuf *m, void *arg)
 {
 	u_int cnt;
 	int dofree;
@@ -249,10 +249,10 @@
 		 * Do the free, should be safe.
 		 */
 		if (m->m_ext.ext_type == EXT_PACKET) {
-			uma_zfree(zone_pack, m);
+			uma_zfree_arg(zone_pack, m, arg);
 			return;
 		} else if (m->m_ext.ext_type == EXT_CLUSTER) {
-			uma_zfree(zone_clust, m->m_ext.ext_buf);
+			uma_zfree_arg(zone_clust, m->m_ext.ext_buf, arg);
 			m->m_ext.ext_buf = NULL;
 		} else {
 			(*(m->m_ext.ext_free))(m->m_ext.ext_buf,
@@ -266,7 +266,7 @@
 			m->m_ext.ext_buf = NULL;
 		}
 	}
-	uma_zfree(zone_mbuf, m);
+	uma_zfree_arg(zone_mbuf, m, arg);
 }
 
 /*
@@ -1381,4 +1381,19 @@
 	if (m_final)
 		m_freem(m_final);
 	return (NULL);
+}
+
+struct mbuf *
+m_free(struct mbuf *m)
+{
+        struct mbuf *n = m->m_next;
+ 
+#ifdef INVARIANTS
+        m->m_flags |= M_FREELIST;
+#endif
+        if (m->m_flags & M_EXT)
+                mb_free_ext(m, __builtin_return_address(0));
+        else
+                uma_zfree_arg(zone_mbuf, m, __builtin_return_address(0));
+        return n;
 }
diff -u -r /usr/src/sys.old/sys/mbuf.h /usr/src/sys/sys/mbuf.h
--- /usr/src/sys.old/sys/mbuf.h	Fri Jun 24 20:17:31 2005
+++ /usr/src/sys/sys/mbuf.h	Fri Jun 24 20:53:07 2005
@@ -350,10 +350,10 @@
 static __inline struct mbuf	*m_gethdr(int how, short type);
 static __inline struct mbuf	*m_getcl(int how, short type, int flags);
 static __inline struct mbuf	*m_getclr(int how, short type);	/* XXX */
-static __inline struct mbuf	*m_free(struct mbuf *m);
+struct mbuf     *m_free(struct mbuf *m);
 static __inline void		 m_clget(struct mbuf *m, int how);
 static __inline void		 m_chtype(struct mbuf *m, short new_type);
-void				 mb_free_ext(struct mbuf *);
+void				 mb_free_ext(struct mbuf *, void *arg);
 
 static __inline
 struct mbuf *
@@ -404,7 +404,8 @@
 	return (uma_zalloc_arg(zone_pack, &args, how));
 }
 
-static __inline
+#if 0
+static
 struct mbuf *
 m_free(struct mbuf *m)
 {
@@ -414,11 +415,12 @@
 	m->m_flags |= M_FREELIST;
 #endif
 	if (m->m_flags & M_EXT)
-		mb_free_ext(m);
+		mb_free_ext(m, __builtin_return_address(0));
 	else
-		uma_zfree(zone_mbuf, m);
+		uma_zfree_arg(zone_mbuf, m, __builtin_return_address(0));
 	return n;
 }
+#endif
 
 static __inline
 void
diff -u -r /usr/src/sys.old/vm/uma_dbg.c /usr/src/sys/vm/uma_dbg.c
--- /usr/src/sys.old/vm/uma_dbg.c	Fri Jun 24 20:13:27 2005
+++ /usr/src/sys/vm/uma_dbg.c	Sat Jun 25 16:51:42 2005
@@ -64,13 +64,19 @@
 {
 	int cnt;
 	u_int32_t *p;
+	int *ptr;
 
 	cnt = size / sizeof(uma_junk);
+	cnt--;
+	ptr = mem;
+	ptr += cnt;
 
 	for (p = mem; cnt > 0; cnt--, p++)
-		if (*p != uma_junk)
-			panic("Memory modified after free %p(%d) val=%x @ %p\n",
+		if (*p != uma_junk) {
+			printf("This memory last freed by: %x\n", *ptr);
+			printf("Memory modified after free %p(%d) val=%x @ %p\n",
 			    mem, size, *p, p);
+		}
 	return (0);
 }
 
@@ -87,9 +93,11 @@
 	u_int32_t *p;
 
 	cnt = size / sizeof(uma_junk);
+	cnt--;
 
 	for (p = mem; cnt > 0; cnt--, p++)
 		*p = uma_junk;
+	*p = (int)arg;
 }
 
 /*


More information about the freebsd-current mailing list