DragonFlyBSD Kernel Audit
DF-2231 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/libprop/prop_kern.c b/sys/libprop/prop_kern.c
--- a/sys/libprop/prop_kern.c
+++ b/sys/libprop/prop_kern.c
@@ -388,20 +388,34 @@
 {
 	prop_object_t obj = NULL;
 	char *buf;
+	size_t len = pref->pref_len;
 	int error;
 
 	/*
+	 * Sanity-check the user-supplied length: it must be non-zero and
+	 * within the declared proplib copy-in limit.  Without this guard a
+	 * hostile plistref drives an unbounded kmalloc()+copyin() (kernel
+	 * memory-exhaustion DoS, and pref_len + 1 wraps to 0 when
+	 * pref_len == SIZE_MAX).  prop_object_copyin_limit was already
+	 * declared for exactly this purpose but was never consulted.
+	 */
+	if (len == 0 || len > (size_t)prop_object_copyin_limit)
+		return (E2BIG);
+
+	/*
 	 * Allocate an extra byte so we can guarantee NUL-termination.
 	 *
 	 * Allow malloc to fail in case pmap would be exhausted.
 	 */
-	buf = kmalloc(pref->pref_len + 1, M_TEMP, M_WAITOK);
-	error = copyin(pref->pref_plist, buf, pref->pref_len);
+	buf = kmalloc(len + 1, M_TEMP, M_WAITOK | M_NULLOK);
+	if (buf == NULL)
+		return (ENOMEM);
+	error = copyin(pref->pref_plist, buf, len);
 	if (error) {
 		kfree(buf, M_TEMP);
 		return (error);
 	}
-	buf[pref->pref_len] = '\0';
+	buf[len] = '\0';
 
 	switch (type) {
 	case PROP_TYPE_ARRAY: