mirror of
https://github.com/uutils/coreutils.git
synced 2025-12-23 08:47:37 +00:00
cp: ensured UID/GID stripping only for unix systems and added test
Signed-off-by: Darius-Constantin <darius.constantin04@stud.acs.upb.ro>
This commit is contained in:
parent
e9870f9325
commit
308ef1f7cb
2 changed files with 63 additions and 4 deletions
|
|
@ -1663,6 +1663,7 @@ pub(crate) fn copy_attributes(
|
|||
let context = &*format!("{} -> {}", source.quote(), dest.quote());
|
||||
let source_metadata =
|
||||
fs::symlink_metadata(source).map_err(|e| CpError::IoErrContext(e, context.to_owned()))?;
|
||||
#[cfg(unix)]
|
||||
let mut ownership_failed = false;
|
||||
|
||||
// Ownership must be changed first to avoid interfering with mode change.
|
||||
|
|
@ -1710,10 +1711,33 @@ pub(crate) fn copy_attributes(
|
|||
// do nothing, since every symbolic link has the same
|
||||
// permissions.
|
||||
if !dest.is_symlink() {
|
||||
let mut permissions = source_metadata.permissions();
|
||||
if ownership_failed {
|
||||
permissions.set_mode(permissions.mode() & !(libc::S_ISUID | libc::S_ISGID));
|
||||
}
|
||||
let permissions = source_metadata.permissions();
|
||||
|
||||
#[cfg(unix)]
|
||||
let permissions = {
|
||||
let mut perms = permissions;
|
||||
if ownership_failed {
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "macos",
|
||||
target_os = "freebsd",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
let mask = libc::S_ISUID | libc::S_ISGID;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "macos",
|
||||
target_os = "freebsd",
|
||||
target_os = "redox",
|
||||
))]
|
||||
let mask = (libc::S_ISUID | libc::S_ISGID) as u32;
|
||||
|
||||
perms.set_mode(perms.mode() & !mask);
|
||||
}
|
||||
perms
|
||||
};
|
||||
|
||||
fs::set_permissions(dest, permissions)
|
||||
.map_err(|e| CpError::IoErrContext(e, context.to_owned()))?;
|
||||
// FIXME: Implement this for windows as well
|
||||
|
|
|
|||
|
|
@ -7400,3 +7400,38 @@ fn test_cp_recurse_verbose_output_with_symlink_already_exists() {
|
|||
.no_stderr()
|
||||
.stdout_is(output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_cp_preserve_strip_setuid() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let source = "/bin/sh";
|
||||
let destination = "sh_copy";
|
||||
|
||||
ucmd.arg("-p").arg(source).arg(destination).succeeds();
|
||||
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let mode = at.metadata(destination).permissions().mode();
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "macos",
|
||||
target_os = "freebsd",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
let mask = libc::S_ISUID | libc::S_ISGID;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "macos",
|
||||
target_os = "freebsd",
|
||||
target_os = "redox",
|
||||
))]
|
||||
let mask = (libc::S_ISUID | libc::S_ISGID) as u32;
|
||||
|
||||
assert_eq!(
|
||||
mode & mask,
|
||||
0,
|
||||
"SetUID/SetGID need to be stripped if ownership preservation fails."
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue