fix(controller): string resvals own their bytes -- rejoin use-after-free killed new primary (bug-1851)
update_val_res() memcpy'd the xce_val_t into w->host.resvals, so the "type"/"model" string resources aliased the interned xstrings owned by w->host.attrs. rejoin_worker() drops the old attrs strings, then apply_join_state() -> resync_arm_round() resolves the previous join's still-outstanding round, firing the worker hooks before add_hostattrs_resvals() re-seeds resvals; the apiserver hook's collect_resval() strdup()ed the freed hostmodel. Live: a newly promoted primary died ~8s after election during an HA soak. A string resval now stores a private strdup (taken before the old copy is freed), and the owning arrays free their entries: host.resvals gets kill_resval (replacing the FIXME NULL killer) and c->sharedinst's resval_obj_killer (previously a no-op) frees the string and the value -- both also leaked every xce_val_t before. Also closes the same alias for worker-reported string resvals and config values. Regression test: test_rejoin_worker_string_resvals_survive_outstanding_round (RED reproduced the live ASAN stack; GREEN after). meson test 109/109. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ac033f4783
commit
ca4db13a79
5 changed files with 199 additions and 4 deletions
|
|
@ -1561,11 +1561,19 @@ static void queue_obj_killer(void* arg)
|
|||
}
|
||||
}
|
||||
|
||||
/* bug-1851: c->sharedinst owns each xce_val_t (update_val_res, worker.c)
|
||||
* and, for a string value, a private strdup()ed copy. */
|
||||
static void resval_obj_killer(void* arg)
|
||||
{
|
||||
if (arg == NULL) {
|
||||
xce_val_t* v = (xce_val_t*)arg;
|
||||
|
||||
if (v == NULL) {
|
||||
return;
|
||||
}
|
||||
if (v->which == Value_u_svalue) {
|
||||
FREEUP(v->u.svalue);
|
||||
}
|
||||
free(v);
|
||||
}
|
||||
|
||||
static void config_obj_killer(void* arg)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue