DragonFlyBSD Kernel Audit
DF-2571 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netgraph/ng_device.c b/sys/netgraph/ng_device.c
--- a/sys/netgraph/ng_device.c
+++ b/sys/netgraph/ng_device.c
@@ -45,6 +45,8 @@
 #include <netgraph/ng_message.h>
 #include <netgraph/netgraph.h>
 
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
 #include "ng_device.h"
 
 /* turn this on for verbose messages */
@@ -506,11 +508,20 @@
 ngdread(cdev_t dev, struct uio *uio, int flag)
 {
 	int ret = 0, amnt;
-	char buffer[uio->uio_resid+1];
+	char *buffer;
 	struct ngd_softc *sc = &ngd_softc;
 	struct ngd_connection * connection = NULL;
 	struct ngd_connection * tmp;
 
+	/* Cap the transfer to the queue size to avoid huge allocations and
+	 * to prevent a user-controlled VLA from overflowing the kernel stack. */
+	if (uio->uio_resid > NGD_QUEUE_SIZE)
+		return(EINVAL);
+
+	buffer = kmalloc(NGD_QUEUE_SIZE + 1, M_DEVBUF, M_WAITOK);
+	if (buffer == NULL)
+		return(ENOMEM);
+
 #ifdef NGD_DEBUG
 	kprintf("%s()\n", __func__);
 #endif /* NGD_DEBUG */
@@ -522,6 +533,7 @@
 	}
 	if(connection == NULL) {
 		kprintf("%s(): connection still NULL, no dev found\n", __func__);
+		kfree(buffer, M_DEVBUF);
 		return(-1);
 	}
 
@@ -538,10 +550,12 @@
 			goto error;
 
 	}
+	kfree(buffer, M_DEVBUF);
 	return(0);
 
 error:
 	kprintf("%s(): uiomove returns error %d\n", __func__, ret);
+	kfree(buffer, M_DEVBUF);
 	/* do error cleanup here */
 	return(ret);
 }
@@ -559,12 +573,23 @@
 	int ret;
 	int error = 0;
 	struct mbuf *m;
-	char buffer[uio->uio_resid];
+	char *buffer;
 	int len = uio->uio_resid;
 	struct ngd_softc *sc =& ngd_softc;
 	struct ngd_connection * connection = NULL;
 	struct ngd_connection * tmp;
 
+	/* Bound the transfer to a sane maximum so a user-controlled VLA cannot
+	 * overflow the 16 KB kernel thread stack. */
+	if (len <= 0)
+		return(0);
+	if ((size_t)len > IP_MAXPACKET)
+		return(EIO);
+
+	buffer = kmalloc(len, M_DEVBUF, M_WAITOK);
+	if (buffer == NULL)
+		return(ENOMEM);
+
 #ifdef NGD_DEBUG
 	kprintf("%s()\n", __func__);
 #endif /* NGD_DEBUG */
@@ -577,17 +602,17 @@
 
 	if(connection == NULL) {
 		kprintf("%s(): connection still NULL, no dev found\n", __func__);
+		kfree(buffer, M_DEVBUF);
 		return(-1);
 	}
 
-	if (len > 0) {
-		if ((ret = uiomove((caddr_t)buffer, len, uio)) != 0)
-			goto error;
-	} else
-		kprintf("%s(): len <= 0 : supposed to happen?!\n", __func__);
+	if ((ret = uiomove((caddr_t)buffer, len, uio)) != 0)
+		goto error;
 
 	m = m_devget(buffer, len, 0, NULL);
 
+	kfree(buffer, M_DEVBUF);
+
 	NG_SEND_DATA_ONLY(error, connection->active_hook, m);
 
 	return(0);
@@ -595,6 +620,7 @@
 error:
 	/* do error cleanup here */
 	kprintf("%s(): uiomove returned err: %d\n", __func__, ret);
+	kfree(buffer, M_DEVBUF);
 
 	return(ret);
 }