Skip to content

Conversation

@mattsu2020
Copy link
Contributor

Summary

Fix cross-filesystem mv (EXDEV copy+delete fallback) so that file ownership does not change to the invoking user (e.g. root) when moving a file across filesystems.

Fixes #9635.

Background / Problem

When mv cannot rename(2) across devices (EXDEV), uutils falls back to copy+delete. The copy path used std::fs::copy, which creates the destination owned by the caller. If root moves a file owned by another user to a different filesystem, the destination ends up owned by root (compatibility + security concern).

Changes

  • On Unix, preserve uid/gid and mode after the copy step in the EXDEV fallback:
    • regular files (including the hardlink-aware copy path)
    • directories (including recursively created subdirectories)
    • symlinks (use lchown, do not follow)
    • FIFOs
  • Restore mode after chown to keep correct permission bits (since chown may clear setuid/setgid).
  • Add a Linux-only regression test that runs only as root and verifies uid/gid are preserved across partitions (/dev/shm tmpfs).
  • Address clippy (bind_instead_of_map) in the copy path.

Testing

  • cargo test -p uu_mv
  • cargo clippy -p uu_mv -- -D warnings

related
#9635

… Unix

Add functions to preserve file ownership (UID/GID) and permissions (mode) during mv operations when fs::rename fails and falls back to copy+remove. This ensures consistency with GNU mv behavior across filesystems, applying preservation in rename fallbacks for files, directories, symlinks, FIFOs, and recursive copies. Changes are Unix-specific, using libc::chown/lchown and fs::set_permissions.
Replace and_then with map in rename_file_fallback's copy operation for Unix systems, as the inner closure performs side effects and returns unit, making map more idiomatic than chaining with Ok(()). This improves code readability without altering behavior.
@github-actions
Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/tail/overlay-headers (passes in this run but fails in the 'main' branch)

@oech3
Copy link
Contributor

oech3 commented Dec 20, 2025

Would you try to make the test rootless?: #8605 (comment)

Add a new Linux-only test to verify cross-device move behavior using user namespaces and tmpfs mounts, avoiding sudo. This mirrors GNU's part-fail scenario for directories containing dangling symlinks, ensuring the mv command preserves symlinks correctly in rootless environments.
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.

[BUG/Compatibility BUG/Security BUG] File ownership changes when a file is mv'ed by root to a different file system.

2 participants