Skip to content

fix: eliminate TOCTOU races in ln and tac by deferring is_dir() checks#10991

Open
abendrothj wants to merge 6 commits intouutils:mainfrom
abendrothj:fix/is_dir_TOCTOU_and_err_msgs
Open

fix: eliminate TOCTOU races in ln and tac by deferring is_dir() checks#10991
abendrothj wants to merge 6 commits intouutils:mainfrom
abendrothj:fix/is_dir_TOCTOU_and_err_msgs

Conversation

@abendrothj
Copy link
Contributor

@abendrothj abendrothj commented Feb 17, 2026

ln: call hard_link() first, check is_dir() only on failure for diagnostics
tac: remove is_dir()/metadata() pre-checks, open file directly and let OS report errors (EISDIR, ENOENT)

Matches GNU coreutils behavior: operate first, diagnose after.

"it's better to ask for forgiveness, rather than for permission"

Closes #9450

@abendrothj abendrothj force-pushed the fix/is_dir_TOCTOU_and_err_msgs branch 2 times, most recently from bcf8fdc to e177167 Compare February 17, 2026 08:40
@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/misc/io-errors. tests/misc/io-errors is passing on 'main'. Maybe you have to rebase?
Skipping an intermittent issue tests/pr/bounded-memory (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/dd/no-allocate is now passing!
Congrats! The gnu test tests/seq/seq-epipe is now passing!

@abendrothj abendrothj force-pushed the fix/is_dir_TOCTOU_and_err_msgs branch from dffafc3 to 9cf958c Compare February 17, 2026 09:31
@codspeed-hq
Copy link

codspeed-hq bot commented Feb 17, 2026

Merging this PR will degrade performance by 3.07%

❌ 1 regressed benchmark
✅ 287 untouched benchmarks
⏩ 38 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation cp_large_file[16] 380.5 µs 392.5 µs -3.07%

Comparing abendrothj:fix/is_dir_TOCTOU_and_err_msgs (a3a28ef) with main (b439534)

Open in CodSpeed

Footnotes

  1. 38 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/date/date-locale-hour. tests/date/date-locale-hour is passing on 'main'. Maybe you have to rebase?
Congrats! The gnu test tests/dd/no-allocate is now passing!

ln: call hard_link() first, check is_dir() only on failure for diagnostics
tac: remove is_dir()/metadata() pre-checks, open file directly and let OS report errors (EISDIR, ENOENT)

Closes uutils#9450
- Remove `(os error 28)` from test_failed_write_is_reported expectation
  to match the intentional strip_errno() behavior
@abendrothj abendrothj force-pushed the fix/is_dir_TOCTOU_and_err_msgs branch from 8af5b77 to ac10014 Compare February 17, 2026 09:49
@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/date/date-locale-hour. tests/date/date-locale-hour is passing on 'main'. Maybe you have to rebase?
GNU test failed: tests/tail/pipe-f2. tests/tail/pipe-f2 is passing on 'main'. Maybe you have to rebase?
Skipping an intermittent issue tests/pr/bounded-memory (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/tail/tail-n0f is now being skipped but was previously passing.
Congrats! The gnu test tests/dd/no-allocate is now passing!
Congrats! The gnu test tests/seq/seq-epipe is now passing!

@github-actions
Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/pr/bounded-memory (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/dd/no-allocate is now passing!

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.

Using Path::is_dir() leads to many TOCTOU races.

1 participant