Skip to content

cp: fix -p to not preserve xattrs by default#9708

Open
AnarchistHoneybun wants to merge 1 commit into
uutils:mainfrom
AnarchistHoneybun:bug/cp-preserve-xattr-9704
Open

cp: fix -p to not preserve xattrs by default#9708
AnarchistHoneybun wants to merge 1 commit into
uutils:mainfrom
AnarchistHoneybun:bug/cp-preserve-xattr-9704

Conversation

@AnarchistHoneybun
Copy link
Copy Markdown
Contributor

Fixes #9704

The -p flag should only preserve mode, ownership, and timestamps, matching GNU cp behavior. Extended attributes require explicit --preserve=xattr or -a (archive mode).

Changed Attributes::DEFAULT to set xattr preservation to No, preventing unintended security risks and filesystem compatibility issues.

Adds regression test.

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/cp/acl. tests/cp/acl is passing on 'main'. Maybe you have to rebase?

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Dec 19, 2025

Merging this PR will not alter performance

✅ 309 untouched benchmarks
⏩ 46 skipped benchmarks1


Comparing AnarchistHoneybun:bug/cp-preserve-xattr-9704 (13877ac) with main (0a9fc3e)2

Open in CodSpeed

Footnotes

  1. 46 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.

  2. No successful run was found on main (1f45676) during the generation of this report, so 0a9fc3e was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/cp/acl. tests/cp/acl is passing on 'main'. Maybe you have to rebase?

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/cp/acl. tests/cp/acl is passing on 'main'. Maybe you have to rebase?
Congrats! The gnu test tests/tail/inotify-dir-recreate is now passing!

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/cp/acl. tests/cp/acl is passing on 'main'. Maybe you have to rebase?

Comment thread tests/by-util/test_cp.rs
);

// mode, ownership, and timestamps should be preserved
#[cfg(not(any(target_os = "freebsd", target_os = "macos")))]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think these are redundant because its at the top of the test already

Comment thread tests/by-util/test_cp.rs
use std::process::Command;
use uutests::util::compare_xattrs;

let scene = TestScenario::new(util_name!());
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could you use the at_and_ucmd macro here?

@ChrisDryden
Copy link
Copy Markdown
Collaborator

I think the issue that was provided was an oversimplification and luckily the GNU test catches it.

The issue #9704 is correct that cp -p shouldn't preserve general xattrs, the implementation in PR #9708 is too expansive - it also removes ACL preservation, which GNU cp -p does support.

We need to make a fix with granular xattr handling that preserves ACLs but not other xattrs.

@ChrisDryden
Copy link
Copy Markdown
Collaborator

Maybe combining your approach with changing of the preserve code to also add ACL xattrs?

  /// Copies only ACL-related xattrs (system.posix_acl_*) from source to dest.
  pub fn copy_acl_xattrs<P: AsRef<Path>>(source: P, dest: P) -> std::io::Result<()> {
      for attr_name in xattr::list(&source)? {
          if let Some(name_str) = attr_name.to_str() {
              if name_str.starts_with("system.posix_acl_") {
                  if let Some(value) = xattr::get(&source, &attr_name)? {
                      xattr::set(&dest, &attr_name, &value)?;
                  }
              }
          }
      }
      Ok(())
  }



  handle_preserve(&attributes.mode, || -> CopyResult<()> {
      // existing mode code...

      // then
      #[cfg(all(unix, not(target_os = "android")))]
      copy_acl_xattrs(source, dest)?;

      Ok(())
  })?;

@AnarchistHoneybun
Copy link
Copy Markdown
Contributor Author

i will look into this today

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/cp/acl. tests/cp/acl is passing on 'main'. Maybe you have to rebase?
Congrats! The gnu test tests/tail/inotify-dir-recreate is now passing!

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/cp/acl. tests/cp/acl is passing on 'main'. Maybe you have to rebase?
Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Congrats! The gnu test tests/basenc/bounded-memory is now passing!

Comment thread src/uu/cp/src/cp.rs Outdated
@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Congrats! The gnu test tests/basenc/bounded-memory is now passing!

1 similar comment
@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Congrats! The gnu test tests/basenc/bounded-memory is now passing!

Comment thread src/uu/cp/src/cp.rs Outdated
@@ -16,7 +16,7 @@ use std::os::unix::net::UnixListener;
use std::path::{Path, PathBuf, StripPrefixError};
use std::{fmt, io};
#[cfg(all(unix, not(target_os = "android")))]
use uucore::fsxattr::copy_xattrs;
use uucore::fsxattr::{copy_acl_xattrs, copy_xattrs};
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.

clippy warning 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.

for some reason this doesn't come up for me when I locally run it, should I be adding the openbsd flag here too, that we have on :1722?

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Congrats! The gnu test tests/printf/printf-surprise is now passing!
Note: The gnu test tests/dd/no-allocate was skipped on 'main' but is now failing.
Note: The gnu test tests/misc/write-errors was skipped on 'main' but is now failing.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 5, 2026

GNU testsuite comparison:

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

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/pr/bounded-memory. tests/pr/bounded-memory is passing on 'main'. Maybe you have to rebase?
Note: The gnu test tests/expand/bounded-memory is now being skipped but was previously passing.

@sylvestre sylvestre force-pushed the bug/cp-preserve-xattr-9704 branch from 12ddfdd to c00b554 Compare April 14, 2026 20:19
@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/cp/acl. tests/cp/acl is passing on 'main'. Maybe you have to rebase?
Skip an intermittent issue tests/cut/bounded-memory (fails in this run but passes in the 'main' branch)
Congrats! The gnu test tests/tail/retry is no longer failing!
Congrats! The gnu test tests/cut/cut-huge-range is now passing!

Fixes uutils#9704

The -p flag should only preserve mode, ownership, and timestamps,
matching GNU cp behavior. Extended attributes require explicit
--preserve=xattr or -a (archive mode).

Changed Attributes::DEFAULT to set xattr preservation to No,
preventing unintended security risks and filesystem compatibility
issues.

Adds regression test.
@sylvestre sylvestre force-pushed the bug/cp-preserve-xattr-9704 branch 2 times, most recently from c00b554 to 13877ac Compare April 14, 2026 20:59
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.

cp -p preserves extended attributes

3 participants