DF-3494 / dmesg.txt
Instrumented-module proof (kprintf at every workBuf/encode alloc/free,
one BINARY2ASCII ERANGE call, guest dmesg):
DBG wbuf+ 0xfffff8011821b000 <- struct composite workBuf alloc
DBG elem etype=0xffffffff82606080 off=0 (uint8 version)
DBG elem etype=0xffffffff82606080 off=1 (uint8 spare)
DBG elem etype=0xffffffff82605fc0 off=2 (uint16 arglen)
DBG elem etype=0xffffffff82605ec0 off=4 (hint32 flags)
DBG elem etype=0xffffffff82605f00 off=8 (uint32 token)
DBG elem etype=0xffffffff82605f00 off=12 (uint32 typecookie)
DBG elem etype=0xffffffff82605f00 off=16 (uint32 cmd)
DBG elem etype=0xffffffff82605c40 off=20 (cmdbuf fixedstring -> ng_string_unparse)
DBG strunp off=20 len=19980 <- strlen walks the attacker bytes
DBG enc+ 0xfffff801183c0000 <- ng_encode_string alloc ~80KB
DBG wbuf- 0xfffff8011821b000 invoke <- workBuf freed correctly
!! no "DBG enc-" — encode buffer LEAKED
Per-call leak = the ng_encode_string buffer (strlen(raw)*4+3, raw is
attacker-controlled, len 19980 -> ~80KB). ng_string_unparse's
NG_PARSE_APPEND("%s", s) hits cbuflen (20480) and `return (ERANGE)`
without kfree(s) — sys/netgraph/netgraph/ng_parse.c:727-731.
ng7 fixed exactly this (frees s via ng_parse_append error path).