Skip to content

evidencectl dev: reading a state file refuses a valid file renamed over between lookup and open #2633

Open

Description

@jeremi

What happens

read_owner_file in crates/registry-evidencectl/src/dev.rs looks the state file up by path, then opens it with O_NOFOLLOW, then refuses the read if the opened inode differs from the one it looked up ("owner-only state changed while opening"). State files are replaced by rename. A replacement that lands between the lookup and the open gives a different, perfectly valid inode, so a concurrent evidencectl dev command can refuse a good state file.

bregctl and caseworkctl had the same false refusal and are fixed on the external record projections branch (feat/breg-external-views): the path checks stay before the open, and after the open the descriptor's own fstat is checked (owner, mode, regular file, link count 0 or 1) instead of comparing with a second lookup. O_NOFOLLOW plus the descriptor's fstat describes exactly the inode whose bytes are read, so the invariant holds without the comparison.

Suggested fix

Apply the same change to read_owner_file, with the same deterministic test (a test-only hook after the open that renames a successor over the path, as in safe_path.rs's RACE_HOOK). A hard link or a mode change after the open must still be refused.

Found while verifying the external record projections branch (feat/breg-external-views).

Activity

  1. added
    bugSomething isn't working
    rustRust implementation work.
    on Nov 10, 2026
  2. jeremi commented on Nov 10, 2026

    @jeremi
    MemberAuthor

    Found while building #2634 (read-only external views in BReg); not fixed there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:evidenceEvidence ownership.bugSomething isn't workingrustRust implementation work.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions