DF-3494 / fix.diff
--- 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 */ } |