DragonFlyBSD Kernel Audit
DF-2570 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netgraph/ng_device.c b/sys/netgraph/ng_device.c
index 0000000..1111111 100644
--- a/sys/netgraph/ng_device.c
+++ b/sys/netgraph/ng_device.c
@@ -360,22 +360,21 @@
 		return(-1);
 	}
 
-	buffer = kmalloc(sizeof(char)*m->m_len, M_DEVBUF, M_NOWAIT | M_ZERO);
-	if(buffer == NULL) {
-		kprintf("%s(): ERROR: buffer malloc failed\n", __func__);
-		return(-1);
-	}
-
-	buffer = mtod(m, char *);
-
+	/*
+	 * DF-2570 defense-in-depth fix: operate on the mbuf's data pointer
+	 * directly.  The previous code kmalloc()'d a buffer from M_DEVBUF,
+	 * immediately leaked that pointer by reassigning it to mtod(m),
+	 * and then kfree()'d the mbuf's m_data through the WRONG zone
+	 * (M_DEVBUF), corrupting the mbuf slab and producing a
+	 * double-freeable mbuf when the mbuf was later freed through its
+	 * own zone.  The intermediate buffer served no purpose.
+	 */
 	if( (connection->loc+m->m_len) < NGD_QUEUE_SIZE) {
-	        memcpy(connection->readq+connection->loc, buffer, m->m_len);
+	        memcpy(connection->readq+connection->loc, mtod(m, char *), m->m_len);
 		connection->loc += m->m_len;
 	} else
 		kprintf("%s(): queue full, first read out a bit\n", __func__);
 
-	kfree(buffer, M_DEVBUF);
-
 	return(0);
 }