Skip to content

fix(ipsec-xfrm): preserve CREATE|EXCL duplicates in MockXfrmBackend #416

Description

@VerifiedOrganic

Problem

LinuxXfrmBackend::install_sa and install_policy issue netlink mutations with NLM_F_CREATE | NLM_F_EXCL. A colliding pre-existing object therefore yields the definitive XfrmError::AlreadyExists result and remains unchanged.

MockXfrmBackend currently diverges:

  • install_sa uses map insertion and replaces an existing mock key before returning Ok(());
  • the revised SA map also keys on if_id and permits otherwise identical destination/protocol/SPI/lookup-mark tuples on different XFRM interfaces, but Linux xfrm_state_add collision lookup does not use if_id as an SA uniqueness discriminator;
  • install_policy treats an existing selector/direction/mark/if_id identity as an idempotent Ok(()).

This can make mock-backed tests claim ownership acquisition or represent coexisting SA state that the Linux backend rejects. It is especially unsafe for staged ownership and pre-existing-object coverage in #409.

Required contract

  • An SA install that collides under Linux CREATE|EXCL lookup semantics returns XfrmError::AlreadyExists and does not replace or alter the pre-existing record.
  • For SAs, a different if_id does not make an otherwise colliding destination/protocol/SPI/lookup-mark tuple independently installable. Exact GETSA may verify the returned if_id, but Linux SA create, GET, and delete lookup do not select by it.
  • An exact duplicate policy install returns XfrmError::AlreadyExists and does not replace, duplicate, or alter the pre-existing policy. Policy if_id remains part of the Linux policy lookup identity.
  • Operation capture may record the attempted mutation, but stored state must remain unchanged.

Required tests

  • Install an SA, retry the same Linux lookup identity with different non-identity parameters or key material, assert AlreadyExists, then query and prove the original state remains.
  • Attempt the same SA lookup identity with a different nonzero or absent if_id, assert AlreadyExists, and prove the original if_id and state remain unchanged. Cover scoped-first and unscoped-first cases.
  • Install a policy, retry the same selector/direction/mark/if_id identity with different non-identity parameters or templates, assert AlreadyExists, then prove the original policy remains present exactly once and can be removed exactly once.
  • Cover unscoped and nonzero policy if_id identities.

The regression must exercise the public MockXfrmBackend, not a private test-only backend.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrustPull requests that update rust code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions