Skip to content

mv: chown the open destination file in a cross-device move - #15351

Closed
ozenyunus35 wants to merge 3 commits into
uutils:mainfrom
ozenyunus35:mv-fchown-fd
Closed

ozenyunus35 wants to merge 3 commits into
uutils:mainfrom
ozenyunus35:mv-fchown-fd

Conversation

@ozenyunus35

Copy link
Copy Markdown
Contributor

Part of #14599

The cross-device file copy keeps src_file / dst_file open so a concurrent path swap can't redirect a step to another inode, but preserve_ownership(from, to) still re-stat'ed both paths and changed the owner by path (lchown). The regular-file copy now uses preserve_ownership_fd, which compares the source's stat (taken from the open source fd) with the open destination and calls rustix::fs::fchown on dst_file, like GNU's fchown(4, …). It returns whether the ids match afterwards, so the setuid/setgid stripping is unchanged. With that, the comment above the block holds as written.

Not done here: creating the destination with O_EXCL. The destination can exist when it's being replaced, so I'd rather handle that separately with its own tests. Happy to follow up.

The mv tests pass on macOS (117). The Linux-only inter_partition_copying tests (tmpfs) couldn't run on my machine, so I'm relying on CI for those.

I used an AI assistant to help draft parts of the code and tests; I reviewed the changes and ran the tests myself.

The cross-device file copy keeps the source and destination open so a path
swap cannot redirect a step to another inode, but ownership was still set
by path (lchown). Set it on the open destination descriptor with fchown,
as GNU does, so the comment above the block now holds.

Part of uutils#14599
Comment thread src/uu/mv/src/mv.rs
// as themselves that used to run as someone else. GNU strips the bits
// in that case and so do we.
let ownership_preserved = preserve_ownership(from, to).unwrap_or(false);
let ownership_preserved = preserve_ownership_fd(&src_meta, &dst_file);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

could you please add a test with a setgid file chgrp'ed to a supplementary group? it would cover the fchown path keeping the bit

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added test_mv_cross_device_preserves_setgid_with_supplementary_group: it chgrps a 2755 file to a supplementary group, moves it to /dev/shm and checks both the gid and the setgid bit.

Comment thread src/uu/mv/src/mv.rs Outdated

/// [`preserve_ownership`] for a regular file the cross-device copy just
/// created: the owner is set on the open destination descriptor (`fchown`, as
/// GNU does), not by path, so it lands on the inode that was written.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

please drop the "as GNU does", not needed here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Dropped.

Comment thread tests/by-util/test_mv.rs Outdated
/// destination, and the mode is applied after it.
#[test]
#[cfg(target_os = "linux")]
fn test_mv_cross_device_preserves_setgid_with_supplementary_group() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

almost the same as test_mv_cross_device_preserves_ownership below, could you just set 0o2755 in that one and check the mode there? :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done, I dropped the separate test and test_mv_cross_device_preserves_ownership now sets 0o2755 and checks the mode after the move.

@ozenyunus35

Copy link
Copy Markdown
Contributor Author

Closing this, as I can't follow up on it further. Thanks for the reviews.

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.

2 participants