Skip to content

fix(path_blocking): close TOCTOU between exists() and symlink_metadata() (#192)#243

Closed
SAY-5 wants to merge 2 commits intoTrueNine:devfrom
SAY-5:fix/path-blocking-toctou-192
Closed

fix(path_blocking): close TOCTOU between exists() and symlink_metadata() (#192)#243
SAY-5 wants to merge 2 commits intoTrueNine:devfrom
SAY-5:fix/path-blocking-toctou-192

Conversation

@SAY-5
Copy link
Copy Markdown
Contributor

@SAY-5 SAY-5 commented Apr 29, 2026

Closes #192.

remove_blocking_file checked path.exists() and then called symlink_metadata(path) separately. Between those two syscalls another process could create, replace, or delete the entry — the classic TOCTOU shape. Practically, an entry that disappears between the two stats produces a symlink_metadata NotFound error that gets bubbled to the caller as Err(...), when the previous exists() already reported it absent (we'd want Ok(false)).

Drop the redundant exists() and treat symlink_metadata's NotFound directly as the nothing to remove case. One stat, race-free.

Tests

New remove_blocking_file_returns_false_for_missing_path covers the path that exists() previously short-circuited; the two existing tests (remove_blocking_file_deletes_file / _skips_directory) still pass.

Test plan

  • cargo build --manifest-path sdk/Cargo.toml — clean
  • cargo test --manifest-path sdk/Cargo.toml --lib policy::path_blocking::tests::remove_ — 3/3 pass

(Two pre-existing test failures on macOS in this module — finds_blocking_file_in_directory_path and resolve_blocking_for_file_target — are caused by /var symlink resolution and are unrelated to this patch.)

TrueNine and others added 2 commits April 25, 2026 10:10
Fix two CI failures from previous merge
Closes TrueNine#192.

`remove_blocking_file` checked `path.exists()` and then called
`symlink_metadata(path)` separately. Between those two syscalls
another process could create, replace, or delete the entry — the
classic TOCTOU shape. Practically, an entry that disappears between
the two stats produces a `symlink_metadata` `NotFound` error that
gets bubbled to the caller as `Err(...)`, when the previous
`exists()` already reported it absent (we'd want `Ok(false)`).

Drop the redundant `exists()` and treat `symlink_metadata`'s
`NotFound` directly as the "nothing to remove" case. One stat,
race-free.

Test: new `remove_blocking_file_returns_false_for_missing_path`
covers the path that `exists()` previously short-circuited; the
two existing tests (`remove_blocking_file_deletes_file` /
`_skips_directory`) still pass. (The two
`finds_blocking_file_in_directory_path` / `resolve_blocking_for_file_target`
test failures on macOS are pre-existing `/var` symlink-resolution
issues, unrelated to this patch.)
@SAY-5 SAY-5 requested a review from TrueNine as a code owner April 29, 2026 22:05
@TrueNine TrueNine changed the base branch from main to dev April 30, 2026 08:08
@TrueNine
Copy link
Copy Markdown
Owner

Merged into dev via cherry-pick. The PR base was changed from main to dev, which caused conflicts because dev had diverged significantly. All commits have been cherry-picked onto dev and pushed. Thanks for the contributions!

@TrueNine TrueNine closed this Apr 30, 2026
@TrueNine
Copy link
Copy Markdown
Owner

Thank you for the contribution! All commits have been cherry-picked and merged into the dev branch. 🙏

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.

[Path Blocking] remove_blocking_file 存在 TOCTOU 竞态

2 participants