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
|
|
@ -22,6 +22,21 @@ static size_t worker_datasize(va_list ap)
|
|||
return sz;
|
||||
}
|
||||
|
||||
/* bug-1851: host.resvals owns each xce_val_t (update_val_res, controller
|
||||
* worker.c) and, for a string value, a private strdup()ed copy. */
|
||||
static void kill_resval(void* p)
|
||||
{
|
||||
xce_val_t* v = (xce_val_t*)p;
|
||||
|
||||
if (v == NULL) {
|
||||
return;
|
||||
}
|
||||
if (v->which == Value_u_svalue) {
|
||||
FREEUP(v->u.svalue);
|
||||
}
|
||||
free(v);
|
||||
}
|
||||
|
||||
static void kill_worker(worker_t* w)
|
||||
{
|
||||
dereference(w->host.name);
|
||||
|
|
@ -66,8 +81,7 @@ static int copy_worker(worker_t* dst, xce_worker_t* src)
|
|||
dst->host.attrs->hostmodel = makeString(src->attrs->hostmodel);
|
||||
dst->host.status = src->status;
|
||||
|
||||
/* FIXME: */
|
||||
zarray_init(&(dst->host.resvals), 64, NULL);
|
||||
zarray_init(&(dst->host.resvals), 64, kill_resval);
|
||||
|
||||
dst->host.dead_since = src->dead_since;
|
||||
dst->host.pending_ctrl = src->pending_ctrl;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue