On 24/03/2024 16:42, Bruno Haible wrote:
The cp/preserve-mode test fails on Alpine Linux 3.18.

test-suite.log from Alpine Linux 3.18:


FAIL: tests/cp/preserve-mode
============================


+ mkdir d1 d2
+ chmod 705 d2
+ cp '--no-preserve=mode' -r d2 d3
+ get_mode d1
+ stat '-c%f' d1
+ get_mode d3
+ stat '-c%f' d3
+ test 45ed '=' 41ed
+ fail=1

This is another setgid issue, and looks like a real bug.
It was there since 8.20 (2012) it seems.
cp is not maintaining the setgid bit, that mkdir(2) created.
I can't repro on my Fedora system, but can on Alpine,
where set_acl() falls back to a chmod because it can't set ACLs.
The attached fixes this by including the setgid bit
in the fallback mode if appropriate.

cheers,
Pádraig
From 30039cb23a2cbdc2ef92e7c474bd9d9ae404ffe0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com>
Date: Mon, 25 Mar 2024 22:17:35 +0000
Subject: [PATCH] cp: with --no-preserve=mode ensure set-group-ID bits
 maintained on dirs

This issue was introduced in commit v8.19-145-g24ebca6

* src/copy.c (copy_internal): On systems that don't support ACLs,
the fallback default chmod done on directories should maintain
the set-group-ID, as that's generally auto-set by the system.
* NEWS: Mention the fix.
Reported by Bruno Haible on Alpine (with tests/cp/preserve-mode.sh)
---
 NEWS       | 5 +++++
 src/copy.c | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/NEWS b/NEWS
index a6ec7c6ef..872723e4f 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,11 @@ GNU coreutils NEWS                                    -*- outline -*-
   to preserve ownership" when copying to GNU/Linux CIFS file systems.
   They do this by working around some Linux CIFS bugs.
 
+  cp --no-preserve=mode will correctly maintain set-group-ID bits
+  for created directories.  Previously on systems that didn't support ACLs,
+  cp would have reset the set-group-ID bit on created directories.
+  [bug introduced in coreutils-8.20]
+
   join and uniq now support multi-byte characters better.
   For example, 'join -tX' now works even if X is a multi-byte character,
   and both programs now treat multi-byte characters like U+3000
diff --git a/src/copy.c b/src/copy.c
index 0318e0067..d584a27eb 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -3268,6 +3268,9 @@ skip:
     {
       int default_permissions = S_ISDIR (src_mode) || S_ISSOCK (src_mode)
                                 ? S_IRWXUGO : MODE_RW_UGO;
+      dst_mode = dst_sb.st_mode;
+      if (S_ISDIR (src_mode))  /* Keep set-group-ID for directories.  */
+        default_permissions |= (dst_mode & S_ISGID);
       if (set_acl (dst_name, -1, default_permissions & ~cached_umask ()) != 0)
         return false;
     }
-- 
2.44.0

Reply via email to