From: Pádraig Brady
Date: Tue, 20 Feb 2018 03:10:14 +0000 (-0800) Subject: cp: set appropriate default permissions for special files X-Git-Tag: v8.30~55 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0a85449ddeeeb5b0432df8158db935d8b56b278e;p=thirdparty%2Fcoreutils.git cp: set appropriate default permissions for special files This issue was introduced in commit v8.19-145-g24ebca6 * src/copy.c (copy_internal): When setting default permissions to use with --no-preserve=mode, only set executable bits for directories or sockets. * NEWS: Mention the fix. * tests/cp/preserve-mode.sh: Add a test case. Fixes https://bugs.gnu.org/30534 --- diff --git a/NEWS b/NEWS index 8a9e09eb4f..5fa69285d7 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,11 @@ GNU coreutils NEWS -*- outline -*- that caused -u to sometimes override -n. [bug introduced with coreutils-7.1] + 'cp -a --no-preserve=mode' now sets appropriate default permissions + for non regular files like fifos and character device nodes etc. + Previously it would have set executable bits on created special files. + [bug introduced with coreutils-8.20] + * Noteworthy changes in release 8.29 (2017-12-27) [stable] diff --git a/src/copy.c b/src/copy.c index e050d4199b..4998c83e6a 100644 --- a/src/copy.c +++ b/src/copy.c @@ -1353,7 +1353,10 @@ preserve_metadata: bool access_changed = false; if (!(sb.st_mode & S_IWUSR) && geteuid () != ROOT_UID) - access_changed = fchmod_or_lchmod (dest_desc, dst_name, 0600) == 0; + { + access_changed = fchmod_or_lchmod (dest_desc, dst_name, + S_IRUSR | S_IWUSR) == 0; + } if (!copy_attr (src_name, source_desc, dst_name, dest_desc, x) && x->require_preserve_xattr) @@ -1378,7 +1381,7 @@ preserve_metadata: } else if (x->explicit_no_preserve_mode) { - if (set_acl (dst_name, dest_desc, 0666 & ~cached_umask ()) != 0) + if (set_acl (dst_name, dest_desc, MODE_RW_UGO & ~cached_umask ()) != 0) return_val = false; } else if (omitted_permissions) @@ -2860,7 +2863,9 @@ copy_internal (char const *src_name, char const *dst_name, } else if (x->explicit_no_preserve_mode) { - if (set_acl (dst_name, -1, 0777 & ~cached_umask ()) != 0) + int default_permissions = S_ISDIR (src_mode) || S_ISSOCK (src_mode) + ? S_IRWXUGO : MODE_RW_UGO; + if (set_acl (dst_name, -1, default_permissions & ~cached_umask ()) != 0) return false; } else diff --git a/tests/cp/preserve-mode.sh b/tests/cp/preserve-mode.sh index 1cd173a6cc..3b0aca8e77 100755 --- a/tests/cp/preserve-mode.sh +++ b/tests/cp/preserve-mode.sh @@ -19,7 +19,7 @@ . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src print_ver_ cp -get_mode() { ls -ld "$1" | cut -b-10; } +get_mode() { stat -c%f "$1"; } rm -f a b c umask 0022 @@ -47,4 +47,12 @@ chmod 600 a cp --no-preserve=mode --preserve=all a b || fail=1 test "$(get_mode a)" = "$(get_mode b)" || fail=1 +#fifo test +if mkfifo fifo; then + cp -a --no-preserve=mode fifo fifo_copy || fail=1 + #ensure default perms set appropriate for non regular files + #which wasn't done between v8.20 and 8.29 inclusive + test "$(get_mode fifo)" = "$(get_mode fifo_copy)" || fail=1 +fi + Exit $fail