Download raw body.
FIX: memory leak in relayd(8) config_purge
Hello,
I found a memory leak in relayd's config_purge() when handling
CONFIG_PROTOS.
The current implementation uses two separate loops: the first one
empties the
sc_protos list, which causes the second loop (responsible for the actual
free() calls) to be skipped entirely.
I've verified this with lldb. The second loop is never entered because
TAILQ_FIRST(env->sc_protos) returns NULL after the first loop finishes,
leaving the protocol structures and their members orphaned in the heap:
(lldb) p *env->sc_protos
(protolist) {
tqh_first = NULL
tqh_last = 0x000007fcaf00ee30
}
(lldb) p *env->sc_protos->tqh_last
(protocol *) NULL
(lldb) p ((struct protocol *)0x000007fc3db03000)->tlscapass
(char *) 0x000007fcaf003360 "s3cr3t"
This patch unifies the logic into a single loop to ensure all resources
(rules, tlscerts, styles, and the protocol structure) are properly freed.
Index: usr.sbin/relayd/config.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/config.c,v
diff -u -p -u -p -r1.48 config.c
--- usr.sbin/relayd/config.c 2 Mar 2026 19:28:01 -0000 1.48
+++ usr.sbin/relayd/config.c 30 Mar 2026 21:47:03 -0000
@@ -186,19 +186,13 @@ config_purge(struct relayd *env, u_int r
while ((rule = TAILQ_FIRST(&proto->rules)) != NULL)
rule_delete(&proto->rules, rule);
proto->rulecount = 0;
- }
- }
- if (what & CONFIG_PROTOS && env->sc_protos != NULL) {
- while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) {
- TAILQ_REMOVE(env->sc_protos, proto, entry);
- free(proto->style);
- free(proto->tlscapass);
- while ((keyname =
- TAILQ_FIRST(&proto->tlscerts)) != NULL) {
+ while ((keyname = TAILQ_FIRST(&proto->tlscerts)) != NULL) {
TAILQ_REMOVE(&proto->tlscerts, keyname, entry);
free(keyname->name);
free(keyname);
}
+ free(proto->style);
+ free(proto->tlscapass);
free(proto);
}
env->sc_protocount = 0;
FIX: memory leak in relayd(8) config_purge