Skip to content

LXC state-aware silently adopts an existing container when a generated name collides #865

Description

What

When a request carries no containerId, resolve_container_name mints one:

src/backends/lxc/common/src/state_aware.rs:104-107

if request.container_id.is_empty() {
    return Ok(format!("mxc-{}", mint_random_token()));
}

mint_random_token (id.rs:20-23) is 4 bytes, so 8 hex characters -- 32 bits.

provision then treats an existing container of that name as a success:

src/backends/lxc/common/src/state_aware.rs:479-487

let created = !container.is_defined();
if created {
    container.create(..)?;
}

So a generated name that collides with an existing container is silently
adopted
: provision returns Ok with created: false, and the caller
believes it owns a fresh container it did not create.

Why it matters

Adoption is intentional and documented for a user-supplied id
(lxc_bindings.rs:615) -- the caller named that container, so reattaching to it
is the useful behavior. An auto-generated name carries the opposite intent:
the caller asked for a new container and has no way to know it was handed
someone else's. Both take the identical branch today.

Fix

Have the generated-name path retry rather than adopt: mint, check is_defined,
mint again on collision, and fail after a small bounded number of attempts.
Roughly 10-15 lines, confined to the container_id.is_empty() branch.

Note that MAX_CONTAINER_NAME_LEN = 20 (state_aware.rs:84) is enforced only
for user-supplied ids, and mxc- plus 16 hex characters is 20, so widening the
token would also fit. Keep that out of this fix -- mint_random_token lives
in id.rs and is shared across backends, so widening it is a separate change
with a wider blast radius. Retry-not-adopt is correct on its own and does not
depend on the entropy question.

Provenance

Reported by Copilot on PR #849, verified live against that PR's HEAD. Held out
of the PR deliberately: it changes provision's success semantics, which warrants
its own review.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions