Skip to content

Conversation

@abendrothj
Copy link

@abendrothj abendrothj commented Dec 23, 2025

feat: enable safe traversal on all Unix platforms

Expands the safe_traversal module support from target_os = "linux" to unix, enabling security improvements (specifically preventing TOCTOU races) on macOS and BSDs.

Changes:

  • Feature Guards: Replaced #[cfg(target_os = "linux")] with #[cfg(unix)] in uucore, du, chmod, and rm.
  • Refactoring: Renamed src/uu/rm/src/platform/linux.rs to unix.rs to reflect the broader platform support.
  • Type Safety: Added necessary type casts in safe_traversal.rs and du.rs to handle platform-specific differences in libc types (e.g., mode_t).

Verification:
Verified with cargo test on macOS.

Closes #9747

@github-actions
Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/tee (passes in this run but fails in the 'main' branch)

Copy link
Contributor

@sylvestre sylvestre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plenty of jobs are failing, please fix them

- Use 'as u64' casts with clippy::unnecessary_cast suppression for
  st_nlink and st_ino to handle platform-specific type differences
- Add TOCTOU (time-of-check time-of-use) to cspell dictionary

Fixes compilation errors on FreeBSD, OpenBSD, and Android where
libc types differ from Linux/macOS (st_nlink is u16, st_ino is u32).
The cast is unnecessary on some platforms but required on others,
hence the clippy suppression.
Resolved merge conflict in src/uu/du/src/du.rs by keeping the unix
cfg guard (not target_os = "linux") to align with the PR's goal of
expanding safe_traversal to all Unix platforms.
@abendrothj abendrothj requested a review from sylvestre December 27, 2025 15:11
@sylvestre
Copy link
Contributor

Still a few job failures

@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/cp/cp-mv-enotsup-xattr. tests/cp/cp-mv-enotsup-xattr is passing on 'main'. Maybe you have to rebase?
Note: The gnu test tests/csplit/csplit-io-err was skipped on 'main' but is now failing.

abendrothj and others added 3 commits December 28, 2025 01:10
This commit addresses compilation errors and test failures on macOS and BSD
platforms introduced by the safe_traversal expansion to Unix platforms.

**SELinux Platform Guards (8 files):**
The SELinux module in uucore is Linux-only, gated behind
`#[cfg(all(target_os = "linux", feature = "selinux"))]`. However, code
was only checking `#[cfg(feature = "selinux")]`, causing compilation
failures on macOS/BSDs where uucore::selinux doesn't exist.

Fixed by updating all SELinux feature checks from:
  `#[cfg(feature = "selinux")]`
to:
  `#[cfg(all(feature = "selinux", target_os = "linux"))]`

Modified files:
- src/uu/cp/src/cp.rs (2 locations)
- src/uu/id/src/id.rs (4 locations)
- src/uu/install/src/install.rs (17 locations)
- src/uu/mkdir/src/mkdir.rs (1 location)
- src/uu/mkfifo/src/mkfifo.rs (1 location)
- src/uu/mknod/src/mknod.rs (1 location)
- src/uu/stat/src/stat.rs (2 locations)

**Type Conversion Fix:**
On macOS, `libc::mode_t` is `u16` while `metadata.permissions().mode()`
returns `u32`, causing a type mismatch in rm's safe_traversal code.

Fixed in src/uu/rm/src/platform/unix.rs:320 by adding explicit cast:
  `initial_mode as libc::mode_t`

**Test Fix:**
Updated test_chmod_recursive to expect consistent error messages across
all Unix platforms. With safe_traversal now enabled universally on Unix,
the detailed error format "cannot access 'z': Permission denied" is used
on all platforms, not just Linux.

Modified: tests/by-util/test_chmod.rs

**Verification:**
- ✅ All unit tests pass (chmod, du, rm, cp, id, stat, mkdir, mkfifo, mknod, install, uucore)
- ✅ All functional tests pass
- ✅ cargo build --features feat_os_macos
- ✅ cargo build --features feat_os_unix
- ✅ cargo clippy (macOS & Unix features)
- ✅ cargo fmt --all -- --check
- ✅ chmod integration tests (40/40 passed)
@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/sort/sort-stale-thread-mem. tests/sort/sort-stale-thread-mem is passing on 'main'. Maybe you have to rebase?

Fixes multiple platform-specific type issues in safe_traversal.rs:

1. **Clippy unnecessary_cast warnings** - Add #[allow(clippy::unnecessary_cast)]
   to dev(), mode(), and rdev() methods. These casts are unnecessary on Linux
   where types are already u64/u32, but required on macOS/BSD where:
   - st_dev is i32 (needs cast to u64)
   - st_mode is u16 (needs cast to u32)
   - st_rdev is i32 (needs cast to u64)

2. **Android type mismatch** - Cast st_mode to libc::mode_t in file_type()
   method. On Android, st_mode is u32 but libc::mode_t is u16, causing
   compilation failure when passing to FileType::from_mode().

These fixes match the existing pattern already used for st_ino and st_nlink.

Resolves:
- Style/lint (ubuntu-latest, all, true) - clippy errors
- Style and Lint (unix) - OpenBSD clippy errors
- Test builds (Android x86/x86_64) - type mismatch errors
@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail/assert is no longer failing!

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail/assert is no longer failing!

abendrothj and others added 3 commits December 28, 2025 04:39
…modules & disable safe dir for Redox (assumedly will be handled in another PR but can implement Redox specific version if requested)
@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail/assert is no longer failing!

- Fix type mismatches in rm's unix.rs by casting libc constants to u16 to match st_mode
- Add Redox stubs for safe_traversal to prevent build errors on Redox
- Make locale format tests robust: only enforce strict checks on platforms with locale support (Linux, macOS, BSDs)

These changes ensure safe directory traversal and related utilities build and test cleanly across all Unix targets, including Redox, and CI passes regardless of locale support.
@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail/assert is no longer failing!

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail/assert is no longer failing!

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail/assert is no longer failing!

abendrothj and others added 2 commits December 29, 2025 02:22
…bility

Fixes compilation errors on Redox by properly gating code that depends on
nix crate types (FileStat) which are not available on Redox.

Changes:
- Add direct libc import for Redox (nix::libc not available)
- Gate Metadata struct, impl, and MetadataExt trait (use FileStat)
- Gate metadata_at() and metadata() methods (return Metadata)
- Revert unrelated locale test changes from commit 5704355

The Redox platform lacks support for nix::sys::stat::FileStat, causing
build failures. These items now follow the existing pattern of returning
"safe_traversal is not supported on Redox" errors via gated stub methods.
@github-actions
Copy link

GNU testsuite comparison:

Note: The gnu test tests/id/smack was skipped on 'main' but is now failing.
Note: The gnu test tests/mkdir/smack-no-root was skipped on 'main' but is now failing.
Note: The gnu test tests/mkdir/smack-root was skipped on 'main' but is now failing.

@github-actions
Copy link

GNU testsuite comparison:

Note: The gnu test tests/basenc/bounded-memory is now being skipped but was previously passing.

@abendrothj
Copy link
Author

@sylvestre Would you like the Mac OS test to be updated in the same PR, or save it for another? Also I've gated Redox, under the assumption that redox and non-posix OS implementations would be handled in another PR as well. Let me know!

@sylvestre
Copy link
Contributor

@sylvestre Would you like the Mac OS test to be updated in the same PR, or save it for another? Also I've gated Redox, under the assumption that redox and non-posix OS implementations would be handled in another PR as well. Let me know!

another pr is fine
but for redox, it is a lot of duplication of #[cfg(not(target_os = "redox"))] in the safe_traversal. rs file
it should be simplified (or split in different files)

@abendrothj
Copy link
Author

That should be better, I removed the scattered #[cfg(...redox...)] guards. Since the module is already excluded on Redox in features.rs, the internal guards were redundant.

@github-actions
Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/timeout/timeout (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/env/env-signal-handler is now being skipped but was previously passing.

@github-actions
Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/timeout/timeout (passes in this run but fails in the 'main' branch)

@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/shuf/shuf-reservoir. tests/shuf/shuf-reservoir is passing on 'main'. Maybe you have to rebase?
GNU test failed: tests/sort/sort-stale-thread-mem. tests/sort/sort-stale-thread-mem is passing on 'main'. Maybe you have to rebase?
Skip an intermittent issue tests/tail/overlay-headers (fails in this run but passes in the 'main' branch)

Make safe-traversal feature conditional for chmod and du crates,
enabling compilation on Redox OS which lacks support for the
fstatat syscalls required by uucore's safe_traversal module.

Changes:
- Move safe-traversal to platform-specific dependencies for non-Redox Unix
- Add guards to exclude DirFd usage on Redox
- Provide Redox-specific implementation for chmod's walk_dir_with_context
  using standard filesystem operations
- Add guard to du's new_from_dirfd to match its DirFd import guard

Both utilities now fall back to standard fs operations on Redox.
@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tty/tty-eof is no longer failing!

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tty/tty-eof is no longer failing!

@abendrothj
Copy link
Author

@sylvestre That should do it. Let me know if there's anything else needed for this pr to be merged

@sylvestre
Copy link
Contributor

@sylvestre That should do it. Let me know if there's anything else needed for this pr to be merged

still a bunch of jobs are failing :)

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.

Safe traversal module only enabled on Linux

2 participants