DragonFlyBSD Kernel Audit
DF-2894 / fix.diff
← back to finding ↓ download raw
--- a/sys/kern/kern_environment.c
+++ b/sys/kern/kern_environment.c
@@ -236,6 +236,16 @@
 		spin_lock(&kenv_dynlock);
 		cp = kenv_getstring_dynamic(name, NULL);
 		if (cp != NULL) {
+			/*
+			 * Defense in depth: a dynamic entry can only exceed
+			 * this buffer if it came from the (unvalidated) boot
+			 * environment copy in kenv_init().  Treat oversize
+			 * entries as absent instead of overflowing the stack.
+			 */
+			if (strlen(cp) >= sizeof(buf)) {
+				spin_unlock(&kenv_dynlock);
+				return (NULL);
+			}
 			strcpy(buf, cp);
 			spin_unlock(&kenv_dynlock);
 			len = strlen(buf) + 1;
@@ -579,6 +589,16 @@
 	/* copy the static environment to our dynamic environment */
 	for (i = 0, cp = kern_envp; cp != NULL; cp = kernenv_next(cp)) {
 		len = strlen(cp) + 1;
+		/*
+		 * Enforce the same per-entry limits as ksetenv(9), so the
+		 * fixed-size buffer in kgetenv(9) can never be overflowed
+		 * by a bootloader-supplied string.
+		 */
+		if (len > KENV_MNAMELEN + KENV_MVALLEN) {
+			kprintf("WARNING: kenv: oversize entry (%d bytes), "
+				"ignoring string %s\n", len, cp);
+			continue;
+		}
 		if (i < (KENV_DYNMAXNUM - 1)) {
 			kenv_dynp[i] = kmalloc(len, M_KENV, M_WAITOK);
 			strcpy(kenv_dynp[i++], cp);