⬢ DragonFlyBSD Kernel Audit
DF-3494 / fix.diff
← back to finding ↓ download raw
--- a/sys/netgraph/netgraph/ng_parse.c	2026-09-13 19:46:06.589509183 +0000
+++ b/sys/netgraph/netgraph/ng_parse.c	2026-09-13 19:58:11.272315743 +0000
@@ -725,10 +725,17 @@
 {
 	const char *const raw = (const char *)data + *off;
 	char *const s = ng_encode_string(raw);
+	int error;
 
 	if (s == NULL)
 		return (ENOMEM);
-	NG_PARSE_APPEND("%s", s);
+	error = ksnprintf(cbuf, cbuflen, "%s", s);
+	if (error >= cbuflen) {
+		kfree(s, M_NETGRAPH);
+		return (ERANGE);
+	}
+	cbuf += error;
+	cbuflen -= error;
 	*off += strlen(raw) + 1;
 	kfree(s, M_NETGRAPH);
 	return (0);
@@ -1236,13 +1243,28 @@
 	int error, index;
 	u_char *workBuf;
 
+	/* Like NG_PARSE_APPEND, but jumps to fail so workBuf gets freed */
+#define NG_UNPARSE_APPEND(fmt, args...)				\
+		do {						\
+			int ulen;				\
+								\
+			ulen = ksnprintf((cbuf), (cbuflen),	\
+				fmt , ## args);			\
+			if (ulen >= (cbuflen)) {			\
+				error = ERANGE;				\
+				goto fail;				\
+			}						\
+			(cbuf) += ulen;				\
+			(cbuflen) -= ulen;				\
+		} while (0)
+
 	/* Get workspace for checking default values */
 	workBuf = kmalloc(workSize, M_NETGRAPH, M_NOWAIT);
 	if (workBuf == NULL)
 		return (ENOMEM);
 
 	/* Opening brace/bracket */
-	NG_PARSE_APPEND("%c", (ctype == CT_STRUCT) ? '{' : '[');
+	NG_UNPARSE_APPEND("%c", (ctype == CT_STRUCT) ? '{' : '[');
 
 	/* Do each item */
 	for (index = 0; index < num; index++) {
@@ -1271,18 +1293,18 @@
 		}
 
 		/* Print name= */
-		NG_PARSE_APPEND(" ");
+		NG_UNPARSE_APPEND(" ");
 		if (ctype != CT_STRUCT) {
 			if (index != nextIndex) {
 				nextIndex = index;
-				NG_PARSE_APPEND("%d=", index);
+				NG_UNPARSE_APPEND("%d=", index);
 			}
 			nextIndex++;
 		} else {
 			const struct ng_parse_struct_field *const
 			    fields = type->info;
 
-			NG_PARSE_APPEND("%s=", fields[index].name);
+			NG_UNPARSE_APPEND("%s=", fields[index].name);
 		}
 
 		/* Print value */
@@ -1298,9 +1320,14 @@
 	kfree(workBuf, M_NETGRAPH);
 
 	/* Closing brace/bracket */
-	NG_PARSE_APPEND("%s%c",
+	NG_UNPARSE_APPEND("%s%c",
 	    didOne ? " " : "", (ctype == CT_STRUCT) ? '}' : ']');
 	return (0);
+fail:
+	/* Clean up after failure (workBuf was leaked here before) */
+	kfree(workBuf, M_NETGRAPH);
+	return (error);
+#undef NG_UNPARSE_APPEND
 }
 
 /*
@@ -1621,6 +1648,7 @@
 			strcpy(p, v);
 		}
 	}
+	kfree(cbuf, M_NETGRAPH);
 	return (NULL);		/* no closing quote */
 }