Skip to content

fix: initialize config_gen_ectx on allocation to prevent use-after-poison#546

Merged
3Hren merged 1 commit intomainfrom
fix/config-gen-ectx-init
Mar 18, 2026
Merged

fix: initialize config_gen_ectx on allocation to prevent use-after-poison#546
3Hren merged 1 commit intomainfrom
fix/config-gen-ectx-init

Conversation

@3Hren
Copy link
Member

@3Hren 3Hren commented Mar 18, 2026

Long-story-short: there was random dataplane crash with ASAN build. Now it's gone.

Explanation requires detailing about cp/dp config exchanges.

The cp_config_gen_create and cp_config_gen_create_from allocate cp_config_gen via memory_balloc, which does not(!) zero memory. When the block allocator returns a recycled block, the config_gen_ectx field contains stale data from its previous owner.

The dataplane worker reads this field via ADDR_OF(&cp_config_gen->config_gen_ectx), which computes a relative pointer: stored_offset + &field. With stale (non-zero) content, this resolves to a wild pointer into freed (ASAN-poisoned) memory, causing a use-after-poison crash in worker_loop_round.

The fix explicitly sets config_gen_ectx = NULL right after allocation in both creation paths, so ADDR_OF correctly returns NULL before config_gen_ectx_create has a chance to set the real value.

The fun part: the mock previously contained a workaround. This is no longer needed since the fix is now inside cp_config_gen_create itself.

A regression test (config_gen_test) reproduces the bug by polluting the allocator pool with garbage before calling cp_config_gen_create. Without the fix, the stale offset resolves to a wild pointer and the volatile read triggers UBSAN/ASAN. With the fix, ADDR_OF returns NULL and the access is skipped.

…ison

Long-story-short: there was random dataplane crash with ASAN build. Now
it's gone.

Explanation requires detailing about cp/dp config exchanges.

The `cp_config_gen_create` and `cp_config_gen_create_from` allocate `cp_config_gen`
via `memory_balloc`, which does not(!) zero memory. When the block allocator
returns a recycled block, the `config_gen_ectx` field contains stale data from
its previous owner.

The dataplane worker reads this field via `ADDR_OF(&cp_config_gen->config_gen_ectx)`,
which computes a relative pointer: `stored_offset + &field`. With stale (non-zero)
content, this resolves to a wild pointer into freed (ASAN-poisoned) memory,
causing a `use-after-poison` crash in `worker_loop_round`.

The fix explicitly sets `config_gen_ectx = NULL` right after allocation in both
creation paths, so `ADDR_OF` correctly returns NULL before `config_gen_ectx_create`
has a chance to set the real value.

The fun part: the mock previously contained a workaround. This is no longer needed
since the fix is now inside `cp_config_gen_create` itself.

A regression test (`config_gen_test`) reproduces the bug by polluting the
allocator pool with garbage before calling `cp_config_gen_create`.
Without the fix, the stale offset resolves to a wild pointer and the volatile read triggers
UBSAN/ASAN. With the fix, `ADDR_OF` returns NULL and the access is skipped.
@3Hren 3Hren requested a review from GeorgyKirichenko March 18, 2026 07:22
@3Hren 3Hren merged commit 04739b8 into main Mar 18, 2026
10 checks passed
@3Hren 3Hren deleted the fix/config-gen-ectx-init branch March 18, 2026 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants