fix(raft-drive-async): endpoint-quiescence for bug-1197 vote-ep teardown (task 3.4a)
When the (still-default-OFF) peer-control dispatch flag is ON, raft_cb_become_follower runs as a vtask pool worker and frees every peer vote-ep while other pool workers may still hold those eps' data — a UAF (bug-1197). This makes that path quiescence-safe so the flag can later be flipped ON (deferred to the 4.x prod-flip gate; production stays OFF here). Mechanism (no libxce-wide endpoint refcount; reuses the existing per-ep FIFO + busy serialization): - Deferred teardown-as-vtask: the loser loop, when dispatch is ON and the pool is wired, does per vote-ep endpoint_mark_tearing_down -> iomgr_unmonitor -> enqueue a VTASK_IO/VTASK_LIVENESS teardown vtask bound to that ep. Per-ep busy FIFO makes it run strictly after any in-flight/queued same-ep peer-control vtask; the body NULLs iod->ep before endpoint_fini+free(ep) to disarm run_task's post-body endpoint_unblock_tasks (which would touch the freed ep->lock). OFF / pool-unwired path is byte-for-byte the legacy endpoint_fini. - RCU-like drain closes the dispatch/teardown TOCTOU window: new _Atomic int endpoint_t.dispatch_inflight (+ tearing_down:1 bit). The ON dispatch brackets its flag-check+enqueue with fetch_add/fetch_sub (seq_cst); endpoint_mark_tearing_down sets the flag under ep->lock, releases, then spins until dispatch_inflight drains to 0. So every dispatch that read the flag false finishes its enqueue before mark returns (FIFO-before the teardown vtask); any later dispatch reads the flag set and drops the packet. ep->lock is deliberately NOT held across the enqueue (it inverts with the taskq lock in vtask_eligible); the counter is the lock-free handshake. Drain is bounded: the held window is just a calloc + non-blocking enqueue on the single io_worker. Still open before the production flag flip (4.x): the borrowed-ep race in snapshot_lane_fn/configpush_lane_fn is distinct (slowlane thread vs io_worker RDHUP teardown, not the vtask-pool FIFO) and needs its own per-standby-ep discipline. Tests: test_ha_vep_teardown.c — 5 ASan tests (ordering, late-event drop, run_task unblock disarm, OFF-path unchanged, deterministic mark-drains-inflight-dispatch). xcelib_test 282/0; controller_unit_test EXIT=0; ASan-clean. Adversarial cpp-review: no CRITICAL/HIGH; handshake formally sound, flag-ON path race-free. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S6fDCtXkkEgupu7rUah1y2
This commit is contained in:
parent
bd02064ebc
commit
6d510d8cf4
10 changed files with 1037 additions and 10 deletions
|
|
@ -19800,15 +19800,20 @@
|
|||
"error_message": "Wrong reference: 1100 should be 1197",
|
||||
"file": "src/controller/ha.c",
|
||||
"root_cause": "Used \"1100\" instead of \"1197\"",
|
||||
"fix": "Changed 1100 \u2192 1197",
|
||||
"fix": "FIXED 2026-06-26 (raft-drive-async 3.4a, behind flag default OFF): deferred teardown-as-vtask on the per-ep FIFO + RCU-like dispatch_inflight drain in endpoint_mark_tearing_down. become_follower marks+unmonitors+drains each vote-ep then enqueues a VTASK_IO teardown bound to that ep (runs strictly after any in-flight same-ep peer-ctrl vtask; NULLs iod->ep to disarm run_task post-body unblock). Closes the UAF for the peer-control dispatch path. NOTE: the snapshot/configpush lane borrowed-ep race is distinct and still open before the prod flag flip.",
|
||||
"tags": [
|
||||
"endpoint-quiescence",
|
||||
"fixed",
|
||||
"c",
|
||||
"dispatch_inflight",
|
||||
"task-3.4a",
|
||||
"tearing_down",
|
||||
"auto-detected",
|
||||
"wrong-reference",
|
||||
"c"
|
||||
"wrong-reference"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 2,
|
||||
"last_seen": "2026-06-26T11:05:02.375Z"
|
||||
"last_seen": "2026-06-26"
|
||||
},
|
||||
{
|
||||
"id": "bug-1199",
|
||||
|
|
@ -20043,6 +20048,182 @@
|
|||
],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-06-26"
|
||||
},
|
||||
{
|
||||
"id": "bug-1211",
|
||||
"timestamp": "2026-06-26T15:49:46.434Z",
|
||||
"error_message": "Function not marked async",
|
||||
"file": "src/controller/ha.h",
|
||||
"root_cause": "Function uses await but wasn't declared async",
|
||||
"fix": "Added async modifier",
|
||||
"tags": [
|
||||
"auto-detected",
|
||||
"async-fix",
|
||||
"h"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 2,
|
||||
"last_seen": "2026-06-26T15:49:59.034Z"
|
||||
},
|
||||
{
|
||||
"id": "bug-1212",
|
||||
"timestamp": "2026-06-26T15:50:27.084Z",
|
||||
"error_message": "Function not marked async",
|
||||
"file": "src/controller/ha.c",
|
||||
"root_cause": "Function uses await but wasn't declared async",
|
||||
"fix": "Added async modifier",
|
||||
"tags": [
|
||||
"auto-detected",
|
||||
"async-fix",
|
||||
"c"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 3,
|
||||
"last_seen": "2026-06-26T15:52:41.021Z"
|
||||
},
|
||||
{
|
||||
"id": "bug-1213",
|
||||
"timestamp": "2026-06-26T15:51:29.747Z",
|
||||
"error_message": "Missing guard clause",
|
||||
"file": "src/controller/ha.c",
|
||||
"root_cause": "No early return/throw for edge case: ha_configpush_probe != NULL",
|
||||
"fix": "Added guard clause: if (ha_configpush_probe != NULL)",
|
||||
"tags": [
|
||||
"auto-detected",
|
||||
"guard-clause",
|
||||
"c"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-06-26T15:51:29.747Z"
|
||||
},
|
||||
{
|
||||
"id": "bug-1214",
|
||||
"timestamp": "2026-06-26T15:54:05.463Z",
|
||||
"error_message": "Function not marked async",
|
||||
"file": "src/controller/testsuite/test_ha_liveness.c",
|
||||
"root_cause": "Function uses await but wasn't declared async",
|
||||
"fix": "Added async modifier",
|
||||
"tags": [
|
||||
"auto-detected",
|
||||
"async-fix",
|
||||
"c"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-06-26T15:54:05.463Z"
|
||||
},
|
||||
{
|
||||
"id": "bug-1215",
|
||||
"timestamp": "2026-06-26T15:57:27.700Z",
|
||||
"error_message": "Significant refactor of ",
|
||||
"file": "src/controller/ha.c",
|
||||
"root_cause": "2 lines replaced/restructured",
|
||||
"fix": "Rewrote 8\u219210 lines (2 removed)",
|
||||
"tags": [
|
||||
"auto-detected",
|
||||
"refactor",
|
||||
"c"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-06-26T15:57:27.700Z"
|
||||
},
|
||||
{
|
||||
"id": "bug-1216",
|
||||
"timestamp": "2026-06-26T16:54:57.384Z",
|
||||
"error_message": "Wrong reference: ssl_handshake_done should be tearing_down",
|
||||
"file": "src/include/netio.h",
|
||||
"root_cause": "Used \"ssl_handshake_done\" instead of \"tearing_down\"",
|
||||
"fix": "Changed ssl_handshake_done \u2192 tearing_down",
|
||||
"tags": [
|
||||
"auto-detected",
|
||||
"wrong-reference",
|
||||
"h"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-06-26T16:54:57.384Z"
|
||||
},
|
||||
{
|
||||
"id": "bug-1217",
|
||||
"timestamp": "2026-06-26T16:55:15.332Z",
|
||||
"error_message": "Wrong reference: ssl_handshake_done should be tearing_down",
|
||||
"file": "src/lib/netio.c",
|
||||
"root_cause": "Used \"ssl_handshake_done\" instead of \"tearing_down\"",
|
||||
"fix": "Changed ssl_handshake_done \u2192 tearing_down",
|
||||
"tags": [
|
||||
"auto-detected",
|
||||
"wrong-reference",
|
||||
"c"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-06-26T16:55:15.332Z"
|
||||
},
|
||||
{
|
||||
"id": "bug-1218",
|
||||
"timestamp": "2026-06-26T16:55:48.690Z",
|
||||
"error_message": "Missing guard clause",
|
||||
"file": "src/controller/ha.c",
|
||||
"root_cause": "No early return/throw for edge case: ectx",
|
||||
"fix": "Added guard clause: if (ectx)",
|
||||
"tags": [
|
||||
"auto-detected",
|
||||
"guard-clause",
|
||||
"c"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-06-26T16:55:48.690Z"
|
||||
},
|
||||
{
|
||||
"id": "bug-1219",
|
||||
"timestamp": "2026-06-26T17:07:46.423Z",
|
||||
"error_message": "Significant refactor of ",
|
||||
"file": "src/lib/netio.c",
|
||||
"root_cause": "4 lines replaced/restructured",
|
||||
"fix": "Rewrote 10\u219227 lines (4 removed)",
|
||||
"tags": [
|
||||
"auto-detected",
|
||||
"refactor",
|
||||
"c"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-06-26T17:07:46.424Z"
|
||||
},
|
||||
{
|
||||
"id": "bug-1220",
|
||||
"timestamp": "2026-06-26T17:08:14.641Z",
|
||||
"error_message": "Significant refactor of ",
|
||||
"file": "src/controller/ha.c",
|
||||
"root_cause": "10 lines replaced/restructured",
|
||||
"fix": "Rewrote 22\u219243 lines (10 removed)",
|
||||
"tags": [
|
||||
"auto-detected",
|
||||
"refactor",
|
||||
"c"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-06-26T17:08:14.641Z"
|
||||
},
|
||||
{
|
||||
"id": "bug-1221",
|
||||
"timestamp": "2026-06-26T17:12:06.544Z",
|
||||
"error_message": "Missing error handling in struct",
|
||||
"file": "src/controller/testsuite/test_ha_vep_teardown.c",
|
||||
"root_cause": "Code path had no error handling \u2014 exceptions would propagate uncaught",
|
||||
"fix": "Added try/catch block",
|
||||
"tags": [
|
||||
"auto-detected",
|
||||
"error-handling",
|
||||
"c"
|
||||
],
|
||||
"related_bugs": [],
|
||||
"occurrences": 1,
|
||||
"last_seen": "2026-06-26T17:12:06.544Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue