GNU bug report logs - #79433
9.7: cp(1): lchownat(2/3) fallback bogus?

Previous Next

Package: coreutils;

Reported by: Steffen Nurpmeso <steffen <at> sdaoden.eu>

Date: Thu, 11 Sep 2025 11:51:02 UTC

Severity: normal

Found in version 9.7

To reply to this bug, email your comments to 79433 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Thu, 11 Sep 2025 11:51:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Steffen Nurpmeso <steffen <at> sdaoden.eu>:
New bug report received and forwarded. Copy sent to bug-coreutils <at> gnu.org. (Thu, 11 Sep 2025 11:51:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: bug-coreutils <at> gnu.org
Cc: Steffen Nurpmeso <steffen <at> sdaoden.eu>
Subject: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Thu, 11 Sep 2025 13:49:33 +0200
Hello.

During package update of kbd i got a build error

  cp: failed to preserve ownership for /tmp/.pkgmk/pkg/usr/share/kbd/keymaps/i386/qwertz/sr-latin.map.gz: Operation not supported

This ended up as (kbd 2.9.0: build error (under fakeroot(1)
environment))[1] which was fixed like [2] (-dPR instead of -a).
However we went over

 |>|cp -a is used in the makefile. The -a means no dereference and preserve
 |>|links and other attributes. This should not be a problem if you have
 |>|the same user.
 |> 
 |> GNU coreutils 9.7 cp(1) is of a different opinion:
 |> 
 |>   $ touch xa
 |>   $ ln -s xa xb
 |>   $ cp -a xb xc
 |>   cp: failed to preserve ownership for xc: Operation not supported
 |
 |No. This is security settings on your system.
 |
 |On my laptop:
 |
 |$ touch xa
 |$ ln -s xa xb
 |$ cp -a xb xc

and so i came to

  This is really strange; i have no "security setting", actually,
  only the fs.protected_* sysctls are set.
  I get the failure in the "sticky" /tmp/ as well as as myself in my
  home directory.  Looking at coreutils cp.c the error comes from

        if (x->preserve_ownership)
          {
            if (lchownat (dst_dirfd, relname, p->st.st_uid, p->st.st_gid)
                != 0)
  ...
                    error (0, errno, _("failed to preserve ownership for %s"),
                           quoteaf (dst_name));

  Here there is no lchownat(3/2), and if i do (copied from manual
  and made runnable)

               #include <sys/types.h>
               #include <unistd.h>
               #include <pwd.h>
               #include <grp.h>
    #include <errno.h>
    #include <string.h>
    #include <stdio.h>
    int main(void){
               struct passwd *pwd;
               struct group  *grp;
               int x;

               pwd = getpwnam("steffen");
               grp = getgrnam("steffen");
               x = lchown("xb", pwd->pw_uid, grp->gr_gid);
               fprintf(stderr, "x=%d errno=%s\n", x, strerror(errno));
               return 0;
    }

  i get

    #?148|kent:x$ fakeroot tcc -run t.c
    x=0 errno=Success
    #?0|kent:x$ tcc -run t.c
    x=0 errno=Success

  wherever i try, and so it seems to me the GNU coreutils
  lib/fchownat.c fallback implementation of lchownat() is bogus
  thus??

And so i am here to report that?.

  [1] https://lore.kernel.org/kbd/20250910123724.s2uU6eVo <at> steffen%25sdaoden.eu/T/#m80238c1410528dc960f54dad20a126fa5ecdb059
  [2] https://git.kernel.org/pub/scm/linux/kernel/git/legion/kbd.git/commit/?id=db82eb6f86e6c0b8ac4260e88b88d66e1cd7c077

Ciao,

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Fri, 12 Sep 2025 13:16:02 GMT) Full text and rfc822 format available.

Message #8 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Martin D Kealey <martin <at> kurahaupo.gen.nz>
To: bug-coreutils <at> gnu.org, Steffen Nurpmeso <steffen <at> sdaoden.eu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Fri, 12 Sep 2025 23:15:20 +1000
[Message part 1 (text/plain, inline)]
Hi Steffen

It's important to note the distinction between ENOSYS “Function not
implemented”, which means there's no kernel call available, and  ENOTSUP
“Operation not supported”, which means the system call exists but the
filesystem driver doesn't implement the requested function (either
generally, or not for the target object).

If lchown exists but reports ENOTSUP, then it is extremely unlikely that
fchownat would get a different result, especially when you consider that
lchown may actually be a library call that invokes fchownat.

What filesystem underpins the files you're trying to manipulate in the
example you've given? (Any chance it's NFS?)

-Martin

PS: The English descriptions of those errors are arguably swapped, but
their E* symbols are clear(er).


On Thu, 11 Sept 2025 at 21:49, Steffen Nurpmeso <steffen <at> sdaoden.eu> wrote:

> Hello.
>
> During package update of kbd i got a build error
>
>   cp: failed to preserve ownership for
> /tmp/.pkgmk/pkg/usr/share/kbd/keymaps/i386/qwertz/sr-latin.map.gz:
> Operation not supported
>
> This ended up as (kbd 2.9.0: build error (under fakeroot(1)
> environment))[1] which was fixed like [2] (-dPR instead of -a).
> However we went over
>
>  |>|cp -a is used in the makefile. The -a means no dereference and preserve
>  |>|links and other attributes. This should not be a problem if you have
>  |>|the same user.
>  |>
>  |> GNU coreutils 9.7 cp(1) is of a different opinion:
>  |>
>  |>   $ touch xa
>  |>   $ ln -s xa xb
>  |>   $ cp -a xb xc
>  |>   cp: failed to preserve ownership for xc: Operation not supported
>  |
>  |No. This is security settings on your system.
>  |
>  |On my laptop:
>  |
>  |$ touch xa
>  |$ ln -s xa xb
>  |$ cp -a xb xc
>
> and so i came to
>
>   This is really strange; i have no "security setting", actually,
>   only the fs.protected_* sysctls are set.
>   I get the failure in the "sticky" /tmp/ as well as as myself in my
>   home directory.  Looking at coreutils cp.c the error comes from
>
>         if (x->preserve_ownership)
>           {
>             if (lchownat (dst_dirfd, relname, p->st.st_uid, p->st.st_gid)
>                 != 0)
>   ...
>                     error (0, errno, _("failed to preserve ownership for
> %s"),
>                            quoteaf (dst_name));
>
>   Here there is no lchownat(3/2), and if i do (copied from manual
>   and made runnable)
>
>                #include <sys/types.h>
>                #include <unistd.h>
>                #include <pwd.h>
>                #include <grp.h>
>     #include <errno.h>
>     #include <string.h>
>     #include <stdio.h>
>     int main(void){
>                struct passwd *pwd;
>                struct group  *grp;
>                int x;
>
>                pwd = getpwnam("steffen");
>                grp = getgrnam("steffen");
>                x = lchown("xb", pwd->pw_uid, grp->gr_gid);
>                fprintf(stderr, "x=%d errno=%s\n", x, strerror(errno));
>                return 0;
>     }
>
>   i get
>
>     #?148|kent:x$ fakeroot tcc -run t.c
>     x=0 errno=Success
>     #?0|kent:x$ tcc -run t.c
>     x=0 errno=Success
>
>   wherever i try, and so it seems to me the GNU coreutils
>   lib/fchownat.c fallback implementation of lchownat() is bogus
>   thus??
>
> And so i am here to report that?.
>
>   [1]
> https://lore.kernel.org/kbd/20250910123724.s2uU6eVo <at> steffen%25sdaoden.eu/T/#m80238c1410528dc960f54dad20a126fa5ecdb059
>   [2]
> https://git.kernel.org/pub/scm/linux/kernel/git/legion/kbd.git/commit/?id=db82eb6f86e6c0b8ac4260e88b88d66e1cd7c077
>
> Ciao,
>
> --steffen
> |
> |Der Kragenbaer,                The moon bear,
> |der holt sich munter           he cheerfully and one by one
> |einen nach dem anderen runter  wa.ks himself off
> |(By Robert Gernhardt)
>
>
>
>
[Message part 2 (text/html, inline)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Fri, 12 Sep 2025 13:17:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Fri, 12 Sep 2025 13:40:02 GMT) Full text and rfc822 format available.

Message #14 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Martin D Kealey <martin <at> kurahaupo.gen.nz>
Cc: bug-coreutils <at> gnu.org, 79433 <at> debbugs.gnu.org,
 Steffen Nurpmeso <steffen <at> sdaoden.eu>
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Fri, 12 Sep 2025 15:39:28 +0200
Hello Martin o/,

[i resort a bit]

Martin D Kealey wrote in
 <CAN_U6MUbv0WHChRYBvgZYrkwbZZ7D9gvpge9N1gvxQJxXsfPAg <at> mail.gmail.com>:
 |On Thu, 11 Sept 2025 at 21:49, Steffen Nurpmeso <steffen <at> sdaoden.eu> wrote:
 ...
 |>   cp: failed to preserve ownership for
 |> /tmp/.pkgmk/pkg/usr/share/kbd/keymaps/i386/qwertz/sr-latin.map.gz:
 |> Operation not supported
 ...
 |>|>|cp -a is used in the makefile. The -a means no dereference and preserve
 |>|>|links and other attributes. This should not be a problem if you have
 |>|>|the same user.
 |>|>
 |>|> GNU coreutils 9.7 cp(1) is of a different opinion:
 |>|>
 |>|>   $ touch xa
 |>|>   $ ln -s xa xb
 |>|>   $ cp -a xb xc
 |>|>   cp: failed to preserve ownership for xc: Operation not supported
 |>|
 |>|No. This is security settings on your system.
 |>|
 |>|On my laptop:
 ...
 |> [.] Looking at coreutils cp.c the error comes from
 |>
 |>         if (x->preserve_ownership)
 |>           {
 |>             if (lchownat (dst_dirfd, relname, p->st.st_uid, p->st.st_gid)
 |>                 != 0)
 |>   ...
 |>                     error (0, errno, _("failed to preserve ownership for
 ...
 |>
 |>   wherever i try, and so it seems to me the GNU coreutils
 |>   lib/fchownat.c fallback implementation of lchownat() is bogus
 ...

 |It's important to note the distinction between ENOSYS “Function not 
 |implemented”, which means there's no kernel call available, and  ENOTSUP “
 |Operation not supported”, which means the system call exists but the 
 |filesystem driver doesn't implement the requested function (either 
 |generally, or not for the target object).
 |
 |If lchown exists but reports ENOTSUP, then it is extremely unlikely that 

(Like i had shown, lchown(3/2) just works.)

 |fchownat would get a different result, especially when you consider that 
 |lchown may actually be a library call that invokes fchownat.
 |
 |What filesystem underpins the files you're trying to manipulate in the 
 |example you've given? (Any chance it's NFS?)

This is BTRFS and tmpfs.  This is glibc 2.40, and Linux kernel
6.1.150.  There is no lchown* except for

  $ grep -r lchown /usr/include/
  /usr/include/llvm/Analysis/TargetLibraryInfo.def:/// int lchown(const char *path, uid_t owner, gid_t group);
  /usr/include/llvm/Analysis/TargetLibraryInfo.def:TLI_DEFINE_ENUM_INTERNAL(lchown)
  /usr/include/llvm/Analysis/TargetLibraryInfo.def:TLI_DEFINE_STRING_INTERNAL("lchown")
  /usr/include/uv.h:UV_EXTERN int uv_fs_lchown(uv_loop_t* loop,
  /usr/include/libmount/libmount.h: * filesystem mounted, but subsequent X-mount.owner=/X-mount.group= lchown(2) failed
  /usr/include/unistd.h:extern int lchown (const char *__file, __uid_t __owner, __gid_t __group)
  /usr/include/bits/syscall.h:#ifdef __NR_lchown
  /usr/include/bits/syscall.h:# define SYS_lchown __NR_lchown
  /usr/include/bits/syscall.h:#ifdef __NR_lchown32
  /usr/include/bits/syscall.h:# define SYS_lchown32 __NR_lchown32
  /usr/include/asm/unistd_x32.h:#define __NR_lchown (__X32_SYSCALL_BIT + 94)
  /usr/include/asm/unistd_64.h:#define __NR_lchown 94
  /usr/include/asm/unistd_32.h:#define __NR_lchown 16
  /usr/include/asm/unistd_32.h:#define __NR_lchown32 198
  /usr/include/python3.12/pyconfig.h:/* Define to 1 if you have the 'lchown' function. */

 |-Martin
 |
 |PS: The English descriptions of those errors are arguably swapped, but 
 |their E* symbols are clear(er).
 --End of <CAN_U6MUbv0WHChRYBvgZYrkwbZZ7D9gvpge9N1gvxQJxXsfPAg <at> mail.gmail\
 .com>

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Fri, 12 Sep 2025 13:40:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Fri, 12 Sep 2025 15:18:02 GMT) Full text and rfc822 format available.

Message #20 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Steffen Nurpmeso <steffen <at> sdaoden.eu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Fri, 12 Sep 2025 08:17:26 -0700
On 2025-09-11 04:49, Steffen Nurpmeso wrote:
>              if (lchownat (dst_dirfd, relname, p->st.st_uid, p->st.st_gid)
>                  != 0)
>    ...
>                      error (0, errno, _("failed to preserve ownership for %s"),
>                             quoteaf (dst_name));
> 
>    Here there is no lchownat(3/2),

No kernel or C library has lchownat; that's a convenience function 
defined in coreutils/lib/openat.h (taken from Gnulib), equivalent to 
fchownat (..., AT_SYMLINK_NOFOLLOW).

What does "strace cp -a xb xc" say? I see this:

  ...
  geteuid32()                             = 1000
  openat(AT_FDCWD, "xb", O_RDONLY|O_LARGEFILE|O_PATH|O_DIRECTORY) = -1 
ENOENT (No such file or directory)
  statx(AT_FDCWD, "xa", 
AT_STATX_SYNC_AS_STAT|AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, 
STATX_BASIC_STATS, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID, 
stx_attributes=0, stx_mode=S_IFREG|0664, stx_size=4, ...}) = 0
  lgetxattr("xa", "security.selinux", 
"unconfined_u:object_r:user_tmp_t"..., 255) = 36
  futex(0xf7f7ccc4, FUTEX_WAKE_PRIVATE, 2147483647) = 0
  openat(AT_FDCWD, "/proc/thread-self/attr/fscreate", 
O_RDWR|O_LARGEFILE|O_CLOEXEC) = 3
  write(3, "unconfined_u:object_r:user_tmp_t"..., 36) = 36
  close(3)                                = 0
  openat(AT_FDCWD, "xa", O_RDONLY|O_LARGEFILE|O_NOFOLLOW) = 3
  statx(3, "", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH, 
STATX_BASIC_STATS, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID, 
stx_attributes=0, stx_mode=S_IFREG|0664, stx_size=4, ...}) = 0
  openat(AT_FDCWD, "xb", O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 4
  ioctl(4, BTRFS_IOC_CLONE or FICLONE, 3) = -1 EOPNOTSUPP (Operation 
not supported)
  statx(4, "", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH, 
STATX_BASIC_STATS, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID, 
stx_attributes=0, stx_mode=S_IFREG|0600, stx_size=0, ...}) = 0
  fadvise64_64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
  uname({sysname="Linux", nodename="penguin.cs.ucla.edu", ...}) = 0
  copy_file_range(3, NULL, 4, NULL, 1073741824, 0) = 4
  copy_file_range(3, NULL, 4, NULL, 1073741824, 0) = 0
  utimensat(4, NULL, [{tv_sec=1757689789, tv_nsec=946283700} /* 
2025-09-12T08:09:49.946283700-0700 */, {tv_sec=1757689789, 
tv_nsec=946283700} /* 2025-09-12T08:09:49.946283700-0700 */], 0) = 0
  flistxattr(3, NULL, 0)                  = 17
  flistxattr(3, "security.selinux\0", 17) = 17
  fchmod(4, 0100664)                      = 0
  flistxattr(3, NULL, 0)                  = 17
  flistxattr(3, "security.selinux\0", 17) = 17
  openat(AT_FDCWD, "/etc/xattr.conf", O_RDONLY|O_LARGEFILE) = 5
  statx(5, "", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH, 
STATX_BASIC_STATS, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID, 
stx_attributes=0, stx_mode=S_IFREG|0644, stx_size=817, ...}) = 0
  read(5, "# /etc/xattr.conf\n#\n# Format:\n# "..., 4096) = 817
  read(5, "", 4096)                       = 0
  close(5)                                = 0
  openat(AT_FDCWD, "/usr/lib/gconv/gconv-modules.cache", 
O_RDONLY|O_CLOEXEC) = 5
  statx(5, "", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH, 
STATX_BASIC_STATS, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID, 
stx_attributes=0, stx_mode=S_IFREG|0644, stx_size=27010, ...}) = 0
  mmap2(NULL, 27010, PROT_READ, MAP_SHARED, 5, 0) = 0xf7f99000
  close(5)                                = 0
  futex(0xf7f2eee8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
  close(4)                                = 0
  close(3)                                = 0
  ...

What happens if you use fchownat directly? Something like the following:

  #include <errno.h>
  #include <fcntl.h>
  #include <grp.h>
  #include <pwd.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>

  int
  main (void)
  {
    char const *user = getenv ("LOGNAME");
    struct passwd const *pwd = getpwnam (user);
    struct group const *grp = getgrnam (user);
    int x = fchownat (AT_FDCWD, "xb",
		      pwd->pw_uid, grp->gr_gid,
		      AT_SYMLINK_NOFOLLOW);
    if (x < 0)
      perror ("fchownat");
    int y = lchown ("xb", pwd->pw_uid, grp->gr_gid);
    if (y < 0)
      perror ("lchown");
  }

I see this:

  ...
  fchownat(AT_FDCWD, "xb", 1000, 1000, AT_SYMLINK_NOFOLLOW) = 0
  lchown("xb", 1000, 1000)                = 0
  ...




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Sat, 13 Sep 2025 15:21:02 GMT) Full text and rfc822 format available.

Message #23 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Sat, 13 Sep 2025 16:56:05 +0200
Paul Eggert wrote in
 <3fe25ff1-2c46-4d2f-997f-3e9dc9c6ca69 <at> cs.ucla.edu>:
 |On 2025-09-11 04:49, Steffen Nurpmeso wrote:
 |>              if (lchownat (dst_dirfd, relname, p->st.st_uid, p->st.st_gid\
 |>              )
 |>                  != 0)
 |>    ...
 |>                      error (0, errno, _("failed to preserve ownership \
 |>                      for %s"),
 |>                             quoteaf (dst_name));
 |> 
 |>    Here there is no lchownat(3/2),
 |
 |No kernel or C library has lchownat; that's a convenience function 
 |defined in coreutils/lib/openat.h (taken from Gnulib), equivalent to 
 |fchownat (..., AT_SYMLINK_NOFOLLOW).
 |
 |What does "strace cp -a xb xc" say? I see this:

  geteuid()                               = 1000
  openat(AT_FDCWD, "c", O_RDONLY|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
  newfstatat(AT_FDCWD, "b", {st_mode=S_IFLNK|0777, st_size=1, ...}, AT_SYMLINK_NOFOLLOW) = 0
  newfstatat(AT_FDCWD, "c", 0x7ffdf869dea0, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory)
  readlink("b", "a", 2)                   = 1
  symlinkat("a", AT_FDCWD, "c")           = 0
  newfstatat(AT_FDCWD, "c", {st_mode=S_IFLNK|0777, st_size=1, ...}, AT_SYMLINK_NOFOLLOW) = 0
  lchown("c", 1000, 1000)                 = 0
  fchmodat2(AT_FDCWD, "c", 0777, AT_SYMLINK_NOFOLLOW) = -1 ENOSYS (Function not implemented)
^^
  openat(AT_FDCWD, "c", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = 3
  newfstatat(3, "", {st_mode=S_IFLNK|0777, st_size=1, ...}, AT_EMPTY_PATH) = 0
  close(3)                                = 0
  fcntl(1, F_GETFL)                       = 0x2 (flags O_RDWR)
  write(2, "cp: ", 4cp: )                     = 4
  write(2, "failed to preserve ownership for"..., 34failed to preserve ownership for c) = 34
  write(2, ": Operation not supported", 25: Operation not supported) = 25
  write(2, "\n", 1
  )                       = 1
  lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
...

 |What happens if you use fchownat directly? Something like the following:

That just works.

I do not know how

  $ grep -r fchmodat2 /usr/include/
  /usr/include/bits/syscall.h:#ifdef __NR_fchmodat2
  /usr/include/bits/syscall.h:# define SYS_fchmodat2 __NR_fchmodat2

gets into there, the kernel definitely does not have that as via
grep.  Generated at glibc build time via

    # install kernel headers
    make -C /usr/src/linux mrproper
    make -C /usr/src/linux INSTALL_HDR_PATH=$PKG/usr headers_install

 --End of <3fe25ff1-2c46-4d2f-997f-3e9dc9c6ca69 <at> cs.ucla.edu>

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Sat, 13 Sep 2025 17:18:02 GMT) Full text and rfc822 format available.

Message #26 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Steffen Nurpmeso <steffen <at> sdaoden.eu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Sat, 13 Sep 2025 10:17:30 -0700
On 2025-09-13 07:56, Steffen Nurpmeso wrote:

>   |What does "strace cp -a xb xc" say? I see this:
> 
>    geteuid()                               = 1000
>    openat(AT_FDCWD, "c", O_RDONLY|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
>    newfstatat(AT_FDCWD, "b", {st_mode=S_IFLNK|0777, st_size=1, ...}, AT_SYMLINK_NOFOLLOW) = 0
>    newfstatat(AT_FDCWD, "c", 0x7ffdf869dea0, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory)
>    readlink("b", "a", 2)                   = 1
>    symlinkat("a", AT_FDCWD, "c")           = 0
>    newfstatat(AT_FDCWD, "c", {st_mode=S_IFLNK|0777, st_size=1, ...}, AT_SYMLINK_NOFOLLOW) = 0
>    lchown("c", 1000, 1000)                 = 0
>    fchmodat2(AT_FDCWD, "c", 0777, AT_SYMLINK_NOFOLLOW) = -1 ENOSYS (Function not implemented)
> ^^

So far the bug report has been about lchownat. But now you're saying 
that cp fails because fchmodat2 fails. So it sounds like we have been 
barking up the wrong tree by worrying about the chown-related syscalls, 
and that we should instead worry about chmod-related syscalls.


> I do not know how
> 
>    $ grep -r fchmodat2 /usr/include/
>    /usr/include/bits/syscall.h:#ifdef __NR_fchmodat2
>    /usr/include/bits/syscall.h:# define SYS_fchmodat2 __NR_fchmodat2
> 
> gets into there, the kernel definitely does not have that as via
> grep.  Generated at glibc build time via
> 
>      # install kernel headers
>      make -C /usr/src/linux mrproper
>      make -C /usr/src/linux INSTALL_HDR_PATH=$PKG/usr headers_install

Recent glibc fchmodat uses fchmodat2 if available. It assumes fchmodat2 
is available if __ASSUME_FCHMODAT2 is nonzero, and __ASSUME_FCHMODAT2 is 
nonzero if you build glibc with headers from Linux kernel 6.6 or later.

It sounds like your glibc was built with __ASSUME_FCHMODAT2 = 1, but is 
running atop an older kernel lacking fchmodat2. If so, that would 
explain the abovementioned symptoms, and it would be a bug in how your 
glibc was built, not a coreutils bug.




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Sat, 13 Sep 2025 17:37:02 GMT) Full text and rfc822 format available.

Message #29 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Sat, 13 Sep 2025 19:36:40 +0200
Paul Eggert wrote in
 <34c2ddd8-e258-496f-ac97-797c8982d8c3 <at> cs.ucla.edu>:
 |On 2025-09-13 07:56, Steffen Nurpmeso wrote:
 |>|What does "strace cp -a xb xc" say? I see this:
 |> 
 |>    geteuid()                               = 1000
 |>    openat(AT_FDCWD, "c", O_RDONLY|O_PATH|O_DIRECTORY) = -1 ENOENT \
 |>    (No such file or directory)
 |>    newfstatat(AT_FDCWD, "b", {st_mode=S_IFLNK|0777, st_size=1, ...}, \
 |>    AT_SYMLINK_NOFOLLOW) = 0
 |>    newfstatat(AT_FDCWD, "c", 0x7ffdf869dea0, AT_SYMLINK_NOFOLLOW) \
 |>    = -1 ENOENT (No such file or directory)
 |>    readlink("b", "a", 2)                   = 1
 |>    symlinkat("a", AT_FDCWD, "c")           = 0
 |>    newfstatat(AT_FDCWD, "c", {st_mode=S_IFLNK|0777, st_size=1, ...}, \
 |>    AT_SYMLINK_NOFOLLOW) = 0
 |>    lchown("c", 1000, 1000)                 = 0
 |>    fchmodat2(AT_FDCWD, "c", 0777, AT_SYMLINK_NOFOLLOW) = -1 ENOSYS \
 |>    (Function not implemented)
 |> ^^
 |
 |So far the bug report has been about lchownat. But now you're saying 

Well i am just a user, ok?  I am saying nothing, i had a build
problem caused by cp(1), the kbd guy thankfully fixed that via
-dPR not -a, i then saw it is from a code line that says
lchownat() in coreutils' cp.c, that was all i know.  I stopped
looking into (the horrible and terrible-style) GNU source code
when i switched from Linux to FreeBSD 4.7, which was a fantastic
experience in comparison!

 |that cp fails because fchmodat2 fails. So it sounds like we have been 
 |barking up the wrong tree by worrying about the chown-related syscalls, 
 |and that we should instead worry about chmod-related syscalls.

Seems like that.

 |> I do not know how
 |> 
 |>    $ grep -r fchmodat2 /usr/include/
 |>    /usr/include/bits/syscall.h:#ifdef __NR_fchmodat2
 |>    /usr/include/bits/syscall.h:# define SYS_fchmodat2 __NR_fchmodat2
 |> 
 |> gets into there, the kernel definitely does not have that as via
 |> grep.  Generated at glibc build time via
 |> 
 |>      # install kernel headers
 |>      make -C /usr/src/linux mrproper
 |>      make -C /usr/src/linux INSTALL_HDR_PATH=$PKG/usr headers_install
 |
 |Recent glibc fchmodat uses fchmodat2 if available. It assumes fchmodat2 
 |is available if __ASSUME_FCHMODAT2 is nonzero, and __ASSUME_FCHMODAT2 is 
 |nonzero if you build glibc with headers from Linux kernel 6.6 or later.

Like i said i have the Linux 6.1.* series, and i build glibc with
the Linux kernel that i run (which is a local change, the default
Pkgfile downloads and installs 6.1.86 just for that:

    # install kernel headers
    #make -C $SRC/linux-$_kernel_version mrproper
    #make -C $SRC/linux-$_kernel_version INSTALL_HDR_PATH=$PKG/usr headers_install
    make -C /usr/src/linux mrproper
    make -C /usr/src/linux INSTALL_HDR_PATH=$PKG/usr headers_install
...
    $SRC/$name-$version/configure \
        --prefix=/usr \
        --libdir=/usr/lib \
        --libexecdir=/usr/lib \
        --with-headers=$PKG/usr/include \
        --enable-kernel=5.10 \
        --enable-stack-protector=strong \
        --enable-bind-now \
        --enable-multi-arch \
        --disable-profile \
        --disable-werror \
        --without-gd)

 |It sounds like your glibc was built with __ASSUME_FCHMODAT2 = 1, but is 
 |running atop an older kernel lacking fchmodat2. If so, that would 
 |explain the abovementioned symptoms, and it would be a bug in how your 
 |glibc was built, not a coreutils bug.

No.  It was build exactly like so:

  # Description: The C library used in the GNU system
  # URL: https://www.gnu.org/software/libc/
  # Maintainer: CRUX System Team, core-ports at crux dot nu

  name=glibc
  version=2.40
  release=3
  _kernel_version=6.1.86

  source=(https://ftp.gnu.org/gnu/glibc/glibc-$version.tar.xz
      #https://www.kernel.org/pub/linux/kernel/v6.x/linux-$_kernel_version.tar.xz
      glibc-$version.patch
      hosts resolv.conf nsswitch.conf host.conf ld.so.conf
      locale-gen locale.gen.in)

  build() {
      # install kernel headers
      #make -C $SRC/linux-$_kernel_version mrproper
      #make -C $SRC/linux-$_kernel_version INSTALL_HDR_PATH=$PKG/usr headers_install
      make -C /usr/src/linux mrproper
      make -C /usr/src/linux INSTALL_HDR_PATH=$PKG/usr headers_install
      chown root:root $PKG/usr

      patch -p1 -d $SRC/$name-${version:0:4} -i $SRC/$name-$version.patch

      mkdir $SRC/build
      cd $SRC/build

      export libc_cv_slibdir=/lib

      $SRC/$name-$version/configure \
          --prefix=/usr \
          --libdir=/usr/lib \
          --libexecdir=/usr/lib \
          --with-headers=$PKG/usr/include \
          --enable-kernel=5.10 \
          --enable-stack-protector=strong \
          --enable-bind-now \
          --enable-multi-arch \
          --disable-profile \
          --disable-werror \
          --without-gd
      make
      #make check
      make install_root=$PKG install

      install -m 0644 $SRC/$name-${version:0:4}/nscd/nscd.conf $PKG/etc
      install -d $PKG/var/db/nscd

      install -m 0644 $SRC/{hosts,resolv.conf,nsswitch.conf,host.conf,ld.so.conf} $PKG/etc

      ln -sf ../usr/share/zoneinfo/UTC $PKG/etc/localtime
      install -d $PKG/etc/ld.so.conf.d $PKG/usr/lib/locale
      touch $PKG/etc/ld.so.cache

      install -Dm755 $SRC/locale-gen $PKG/usr/sbin/locale-gen
      install -Dm644 $SRC/locale.gen.in $PKG/etc/locale.gen
      sed -e '1,3d' -e 's|/| |g' -e 's|\\| |g' -e 's|^|#|g' \
          $SRC/$name-$version/localedata/SUPPORTED >> $PKG/etc/locale.gen

      LC_ALL=C ./elf/ld.so --library-path . $PKG/usr/bin/localedef \
          --force --quiet \
          --inputfile=$SRC/$name-$version/localedata/locales/C \
          --charmap=$SRC/$name-$version/localedata/charmaps/UTF-8 \
          $PKG/usr/lib/locale/C.UTF-8 || true

      rm -r $PKG/usr/share/locale \
          $PKG/usr/bin/{tzselect,zdump} \
          $PKG/usr/sbin/zic

      install -Dm644 $SRC/$name-$version/intl/locale.alias \
          $PKG/usr/share/locale/locale.alias
  }


The patch was

  -rw-rw-r-- 1 ports ports 1186584 Jul 24 17:01 glibc-2.40.patch

and created like

  : ${version?'Need $version'}

  curl -L -o .glibc-$version.patch \
          'https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;hp=refs/tags/glibc-'$version';h=refs/heads/release/'$version'/master'

(with $version being 2.40).

That is all i know.

 --End of <34c2ddd8-e258-496f-ac97-797c8982d8c3 <at> cs.ucla.edu>

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Mon, 15 Sep 2025 17:45:02 GMT) Full text and rfc822 format available.

Message #32 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Steffen Nurpmeso <steffen <at> sdaoden.eu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Mon, 15 Sep 2025 10:44:28 -0700
On 2025-09-13 10:36, Steffen Nurpmeso wrote:
> Paul Eggert wrote in
>   |that cp fails because fchmodat2 fails. So it sounds like we have been
>   |barking up the wrong tree by worrying about the chown-related syscalls,
>   |and that we should instead worry about chmod-related syscalls.
> 
> Seems like that.

On further looking at your trace in 
<https://debbugs.gnu.org/cgi/bugreport.cgi?bug=79433#23> it seems that I 
was mistaken. Even though the fchmodat2 syscall fails with ENOSYS, it 
appears that the glibc fchmodat library function then calls openat with 
O_NOFOLLOW|O_PATH and then calls fstatat+AT_EMPTY_PATH, determines that 
"c" is a symlink, and then returns -1 with errno=ENOTSUP.

But then I'm lost. If b is a symlink, I don't see why 'cp -a b c' would 
ever call fchmodat. The coreutils 9.7 source code says that fopr 
symlinks copy_internal should call symlinkat via force_symlinkat 
(copy.c:3117), then fchownat via lchownat (copy.c:3152), then utimensat 
(copy.c:3227), but it should never call fchmodat.

Could you investigate why coreutils 9.7 cp is not behaving the way the 
source code says it should? You can use a debugger, or insert print 
statements, to figure out why in this particular case it is going awry.

Lets get the chmod issue figured out first. We can worry about the chown 
issue later; one thing at a time.





Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Tue, 16 Sep 2025 00:41:01 GMT) Full text and rfc822 format available.

Message #35 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Tue, 16 Sep 2025 02:40:07 +0200
Hello.

Sorry for the late reply.

Paul Eggert wrote in
 <4d962618-fee0-4cbb-b769-6ca61a96aef4 <at> cs.ucla.edu>:
 |On 2025-09-13 10:36, Steffen Nurpmeso wrote:
 |> Paul Eggert wrote in
 |>|that cp fails because fchmodat2 fails. So it sounds like we have been
 |>|barking up the wrong tree by worrying about the chown-related syscalls,
 |>|and that we should instead worry about chmod-related syscalls.
 |> 
 |> Seems like that.
 |
 |On further looking at your trace in 
 |<https://debbugs.gnu.org/cgi/bugreport.cgi?bug=79433#23> it seems that I 
 |was mistaken. Even though the fchmodat2 syscall fails with ENOSYS, it 

Please stop right here.
I followed your advice and rebuilt coreutils 9.7.  I cannot
reproduce the error, strace(1)d flows change due to fchmodat2().
I give the logs below.

  $ grep chown /usr/include/asm/unistd_64.h
  #define __NR_chown 92
  #define __NR_fchown 93
  #define __NR_lchown 94
  #define __NR_fchownat 260

  $ grep fchmod /usr/include/asm/unistd_64.h
  #define __NR_fchmod 91
  #define __NR_fchmodat 268

  $ ll /bin/cp
  -rwxr-xr-x 1 root root 126240 Apr 29 11:59 /bin/cp*

  $ ll src/cp
  -rwxr-x--- 1 steffen steffen 480888 Sep 16 01:18 src/cp*

On my box, since April, quite some things changed (CRUX is rolling
release, except for certain core ports which only get bugfixes).
I cannot reconstruct exact software environment from April.

  $ strings /bin/cp | grep -i gcc:
  GCC: (CRUX-x86_64-multilib) 14.2.0

  $ strings src/cp | grep -i gcc:
  GCC: (CRUX-x86_64-multilib) 14.3.0

That.  glibc 2.40 is here since last Octobre (20th) i would
think, it was updated three or four times (CVEs .. at least).
Kernel is 6.1.* ever since it was declared LTS.

 |appears that the glibc fchmodat library function then calls openat with 
 |O_NOFOLLOW|O_PATH and then calls fstatat+AT_EMPTY_PATH, determines that 
 |"c" is a symlink, and then returns -1 with errno=ENOTSUP.
 |
 |But then I'm lost. If b is a symlink, I don't see why 'cp -a b c' would 
 |ever call fchmodat. The coreutils 9.7 source code says that fopr 
 |symlinks copy_internal should call symlinkat via force_symlinkat 
 |(copy.c:3117), then fchownat via lchownat (copy.c:3152), then utimensat 
 |(copy.c:3227), but it should never call fchmodat.
 |
 |Could you investigate why coreutils 9.7 cp is not behaving the way the 
 |source code says it should? You can use a debugger, or insert print 
 |statements, to figure out why in this particular case it is going awry.
 |
 |Lets get the chmod issue figured out first. We can worry about the chown 
 |issue later; one thing at a time.

So i instrumented the code paths first, which was stupid, since it
just works if compiled now.  I do have the /bin/cp from April. 
Here is the diff.

  --- _bin_cp.log	2025-09-16 01:22:35.366585945 +0200
  +++ _src_cp.log	2025-09-16 01:23:14.693251872 +0200
  @@ -1,40 +1,40 @@
  -execve("/bin/cp", ["/bin/cp", "-a", "xb", "xc"], 0x7ffee5e2ffb8 /* 94 vars */) = 0
  -brk(NULL)                               = 0x55d3bf6d7000
  -mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fbbd5a6c000
  +execve("src/cp", ["src/cp", "-a", "xb", "xc"], 0x7ffcd92e2298 /* 94 vars */) = 0
  +brk(NULL)                               = 0x55b6475d1000
  +mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3595bd8000
   access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
   ...
   openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
  @@ -43,52 +43,106 @@ read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0
  ...
   prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
  -getrandom("\x03\x0b\xe6\x00\xb2\xbe\xbd\x51", 8, GRND_NONBLOCK) = 8
  -brk(NULL)                               = 0x55d3bf6d7000
  -brk(0x55d3bf6f8000)                     = 0x55d3bf6f8000
  +getrandom("\x4f\x4b\xf5\x75\x90\xf4\x18\xef", 8, GRND_NONBLOCK) = 8
  +brk(NULL)                               = 0x55b6475d1000
  +brk(0x55b6475f2000)                     = 0x55b6475f2000
   openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
   fstat(3, {st_mode=S_IFREG|0644, st_size=3061520, ...}) = 0
  -mmap(NULL, 3061520, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fbbd5400000
  +mmap(NULL, 3061520, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3595600000
   close(3)                                = 0
   geteuid()                               = 1000
  +write(2, "PRE DO_COPY\n", 12PRE DO_COPY
  +)           = 12
  +write(2, "DO_COPY\n", 8DO_COPY
  +)                = 8
   openat(AT_FDCWD, "xc", O_RDONLY|O_PATH|O_DIRECTORY) = -1 ENOTDIR (Not a directory)
  +write(2, "WORK2 xb xc\n", 12WORK2 xb xc
  +)           = 12
  +write(2, "COPY_INTERNAL xb -> xc\n", 23COPY_INTERNAL xb -> xc
  +) = 23
   newfstatat(AT_FDCWD, "xb", {st_mode=S_IFLNK|0777, st_size=2, ...}, AT_SYMLINK_NOFOLLOW) = 0
  +write(2, "      10\n", 9      10
  +)               = 9
   newfstatat(AT_FDCWD, "xc", {st_mode=S_IFLNK|0777, st_size=2, ...}, AT_SYMLINK_NOFOLLOW) = 0
   unlinkat(AT_FDCWD, "xc", 0)             = 0
   readlink("xb", "xa", 3)                 = 2
   symlinkat("xa", AT_FDCWD, "xc")         = 0

==DIVERT

  -newfstatat(AT_FDCWD, "xc", {st_mode=S_IFLNK|0777, st_size=2, ...}, AT_SYMLINK_NOFOLLOW) = 0
  -lchown("xc", 1000, 1000)                = 0
  -fchmodat2(AT_FDCWD, "xc", 0777, AT_SYMLINK_NOFOLLOW) = -1 ENOSYS (Function not implemented)
  -openat(AT_FDCWD, "xc", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = 3
  -newfstatat(3, "", {st_mode=S_IFLNK|0777, st_size=2, ...}, AT_EMPTY_PATH) = 0
  -close(3)                                = 0

Like you say -- sysdeps/unix/sysv/linux/fchmodat.c went over
fchmodat_fallback().  How did it get here at all is your question;
well, /bin/cp is stripped, CRUX strips stuff.

  -fcntl(1, F_GETFL)                       = 0x2 (flags O_RDWR)
  -write(2, "cp: ", 4cp: )                     = 4
  -write(2, "failed to preserve ownership for"..., 35failed to preserve ownership for xc) = 35
  -write(2, ": Operation not supported", 25: Operation not supported) = 25
  -write(2, "\n", 1
  -)                       = 1
  +write(2, "      314\n", 10      314
  +)             = 10
...
  +write(2, "      316\n", 10      316
  +)             = 10
  +fchownat(AT_FDCWD, "xc", 1000, 1000, AT_SYMLINK_NOFOLLOW) = 0
  +write(2, "      320\n", 10      320
  +)             = 10
..
  +utimensat(AT_FDCWD, "xc", [{tv_sec=1757977042, tv_nsec=253998375} /* 2025-09-16T00:57:22.253998375+0200 */, {tv_sec=1757977033, tv_nsec=957331866} /* 2025-09-16T00:57:13.957331866+0200 */], AT_SYMLINK_NOFOLLOW) = 0
  +llistxattr("xb", NULL, 0)               = 0
  +llistxattr("xb", 0x7ffdb169b050, 0)     = 0
  +write(2, "do_copy returns 1\n", 18do_copy returns 1
  +)     = 18
   lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
   close(0)                                = 0
   close(1)                                = 0
   close(2)                                = 0
  -exit_group(1)                           = ?
  -+++ exited with 1 +++
  +exit_group(0)                           = ?
  ++++ exited with 0 +++

I do have that /bin/cp.
Btw i note that if i strip src/cp it is much smaller than /bin/cp,
but, different compiler etc.
Well, that will be hard, to get more out of that.  I do not use
debuggers.  Well, i guess i could install gdb and set breakpoint
around symlinkat(), then step and try to look around.

 --End of <4d962618-fee0-4cbb-b769-6ca61a96aef4 <at> cs.ucla.edu>

How likely is a miscompilation of gcc 4.2.0?

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Tue, 16 Sep 2025 03:54:02 GMT) Full text and rfc822 format available.

Message #38 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Steffen Nurpmeso <steffen <at> sdaoden.eu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Mon, 15 Sep 2025 20:53:02 -0700
On 2025-09-15 17:40, Steffen Nurpmeso wrote:
> How likely is a miscompilation of gcc 4.2.0?

I would think not likely, but possible.

If things are working for you know, I wouldn't spend much time worrying 
about it.




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Tue, 16 Sep 2025 12:21:02 GMT) Full text and rfc822 format available.

Message #41 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Tue, 16 Sep 2025 14:20:11 +0200
[Message part 1 (text/plain, inline)]
Paul Eggert wrote in
 <fec712d1-3936-45af-979e-0bc76ad59358 <at> cs.ucla.edu>:
 |On 2025-09-15 17:40, Steffen Nurpmeso wrote:
 |> How likely is a miscompilation of gcc 4.2.0?
 |
 |I would think not likely, but possible.
 |
 |If things are working for you know, I wouldn't spend much time worrying 
 |about it.

i'll attach it plzip(1)ped; i now install gdb, from objdump(1)
alone i cannot figure it out, the codepaths are too mangled for me
having no history with neither coreutils nor glibc.

  $ ldd /bin/cp
  linux-vdso.so.1 (0x00007fffe1e13000)
  libacl.so.1 => /lib/libacl.so.1 (0x00007fcf92d3a000)
  libattr.so.1 => /lib/libattr.so.1 (0x00007fcf92d32000)
  libc.so.6 => /lib/libc.so.6 (0x00007fcf92b42000)
  /lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fcf92d66000)

I could also place the actual libs on the server, just in case
anyone wants the complete picture; seems unnecessary.  It is
absolutely reproducible, so the problem is in the binary for sure.

 --End of <fec712d1-3936-45af-979e-0bc76ad59358 <at> cs.ucla.edu>

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)
[cp-9.7-April.lz (application/x-lzip, attachment)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Tue, 16 Sep 2025 14:38:01 GMT) Full text and rfc822 format available.

Message #44 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Tue, 16 Sep 2025 16:36:58 +0200
Steffen Nurpmeso wrote in
 <20250916122011.vqDfAgh0 <at> steffen%sdaoden.eu>:
 |Paul Eggert wrote in
 | <fec712d1-3936-45af-979e-0bc76ad59358 <at> cs.ucla.edu>:
 ||On 2025-09-15 17:40, Steffen Nurpmeso wrote:
 ||> How likely is a miscompilation of gcc 4.2.0?
 ||
 ||I would think not likely, but possible.
 ...
 |i'll attach it plzip(1)ped; i now install gdb, from objdump(1)
 |alone i cannot figure it out, the codepaths are too mangled for me
 |having no history with neither coreutils nor glibc.
 |
 |  $ ldd /bin/cp
 |  linux-vdso.so.1 (0x00007fffe1e13000)
 |  libacl.so.1 => /lib/libacl.so.1 (0x00007fcf92d3a000)
 |  libattr.so.1 => /lib/libattr.so.1 (0x00007fcf92d32000)
 |  libc.so.6 => /lib/libc.so.6 (0x00007fcf92b42000)
 |  /lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fcf92d6\
 |  6000)
 |
 |I could also place the actual libs on the server, just in case
 ..
 | --End of <fec712d1-3936-45af-979e-0bc76ad59358 <at> cs.ucla.edu>
 --End of <20250916122011.vqDfAgh0 <at> steffen%sdaoden.eu>

So for

	gdb/gdb --args /bin/cp --debug -a xb xc

we enter

	else if (S_ISLNK (src_mode))

at copy.c:3106 since i see

	unlinkat
	readlink <at> plt
	symlinkat <at> plt
	free
	lstat <at> plt [hmm where; lchownat fallback?]
		lstat64
		fstatat64
	lchown <at> plt
		lchown

Thereafter only 10 "??" stepi in between resolved lchown and

	lchmod <at> plt
		fchmodat

which seems to be lchmodat() at line 3312, which makes me wonder
given that -a implies x->preserve_timestamps and thus the
utimensat() path at line 3220+ should have been taken, and,
furthermore, there is line 3256+ saying

  /* The operations beyond this point may dereference a symlink. */
  if (dest_is_symlink)
    return delayed_ok;

and then there was "dest_is_symlink = true;" at line 3109 in the
S_ISLNK() block.  Now my gdb knowledge is exceeded, i hate
debuggers.  And they hate me

 $ curl -O https://ftp.gnu.org/gnu/gdb/gdb-16.3.tar.xz
 % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
 			 Dload  Upload   Total   Spent    Left  Speed
 100 23.3M  100 23.3M    0     0  18748      0  0:21:43  0:21:43 --:--:-- 210080

but that aside.  It would need a debug guru to look at the data,
the file is stripped.  And it is optimized, so if i
"break symlinkat" and then "x/10i $pc"<>"stepi" (sorry, never
debuggers) we see early returns

	(gdb) next
	Single stepping until exit from function symlinkat,
...
	(gdb) x/10i $pc
	=> 0x555555560a15:      mov    %eax,%ebx
	   0x555555560a17:      test   %eax,%eax
	   0x555555560a19:      je     0x5555555609e3
...
	(gdb) x/10i $pc
	=> 0x5555555609e3:      mov    0x118(%rsp),%rax
	   0x5555555609eb:      sub    %fs:0x28,%rax
	   0x5555555609f4:      jne    0x555555560a77
	   0x5555555609fa:      add    $0x128,%rsp
	   0x555555560a01:      mov    %ebx,%eax
	   0x555555560a03:      pop    %rbx
	   0x555555560a04:      pop    %rbp
	   0x555555560a05:      pop    %r12
	   0x555555560a07:      pop    %r13
	   0x555555560a09:      pop    %r14
	[..]
	   0x555555560a0b:      pop    %r15
	   0x555555560a0d:      ret

So we actually left that, which we did not from the C source file
me thinks, so likely gcc spilled code around, anyway it would
require very deep inspection; and for me this is manual, since i
never ever cared for debugger and their support, it could be there
is a smart analyzer tools / extension somewhere which does exactly
that, but this i really do not know.  It seems to me coreutils do
not embed actual compiler and linker flags used somewhere, so the
binary is all i can give, i would think, shall reproduction from
scratch be of interest for some gcc developers maybe.

I have it here, if anyone gives debugger knowledge we can go
deeper, i could maybe even create a ssh guest account if it is
really important, and i have posted the compressed binary which
surely is where the error can be found.

My enthusiasm is hereby extinct, even though i would like to see
the content of the "const struct cp_options *x" as well as
"dest_is_symlink" local variable.
I would think it is a miscompilation of gcc 14.2.

Sorry for the noise, shall nothing further happen.  I, you know,
had that build error and it produced circles, i thought a quick
note is a thing.  You know, is there any just plain "cp -a symlink
symlink" test in coreutils, for example, as i look.

Ciao,

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Tue, 16 Sep 2025 18:52:01 GMT) Full text and rfc822 format available.

Message #47 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Tue, 16 Sep 2025 20:51:03 +0200
Hello again, and however,

Steffen Nurpmeso wrote in
 <20250916143658.Sac81LV7 <at> steffen%sdaoden.eu>:
 |Steffen Nurpmeso wrote in
 | <20250916122011.vqDfAgh0 <at> steffen%sdaoden.eu>:
 ||Paul Eggert wrote in
 || <fec712d1-3936-45af-979e-0bc76ad59358 <at> cs.ucla.edu>:
 |||On 2025-09-15 17:40, Steffen Nurpmeso wrote:
 |||> How likely is a miscompilation of gcc 4.2.0?
 |||
 |||I would think not likely, but possible.
 | ...

Do not laugh, but i can actually reproduce building coreutils in
my current environment in a way that causes the bug to happen.
But i do not know how.
But i can give config.log files.

I know how now.  Just run configure via fakeroot!
Yes!  Ha!!!  And all for free, what a shame.

I attach a tar archives of the two different logfiles, maybe some
GNU build system guru can figure out more.

(btw isn't english funny "[kn]ow [h]ow [n]ow", sounds like
Blackfoot's I am on the Run, or something.)

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Tue, 16 Sep 2025 18:53:02 GMT) Full text and rfc822 format available.

Message #50 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Tue, 16 Sep 2025 20:52:32 +0200
[Message part 1 (text/plain, inline)]
Steffen Nurpmeso wrote in
 <20250916185103.eUaqIy9H <at> steffen%sdaoden.eu>:
 |Steffen Nurpmeso wrote in
 | <20250916143658.Sac81LV7 <at> steffen%sdaoden.eu>:
 ||Steffen Nurpmeso wrote in
 || <20250916122011.vqDfAgh0 <at> steffen%sdaoden.eu>:
 |||Paul Eggert wrote in
 ||| <fec712d1-3936-45af-979e-0bc76ad59358 <at> cs.ucla.edu>:
 ||||On 2025-09-15 17:40, Steffen Nurpmeso wrote:
 ||||> How likely is a miscompilation of gcc 4.2.0?
 ||||
 ||||I would think not likely, but possible.
 || ...
 |But i can give config.log files.
 ...

Sorry, forgot those.

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)
[logfiles.tar.lz (application/x-lzip, attachment)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Tue, 16 Sep 2025 19:08:01 GMT) Full text and rfc822 format available.

Message #53 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Steffen Nurpmeso <steffen <at> sdaoden.eu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Tue, 16 Sep 2025 12:07:42 -0700
On 2025-09-16 07:36, Steffen Nurpmeso wrote:
> My enthusiasm is hereby extinct

Yeah, it's really hard to figure out what went wrong, given that all we 
have is a stripped executable that may not have be built correctly for 
whatever reason. One possibility is some low-level problem with the 
dynamic linker. So you can ignore the rest of this email if you like.

> at copy.c:3106 since i see
> 
> 	unlinkat
> 	readlink <at> plt
> 	symlinkat <at> plt
> 	free
> 	lstat <at> plt [hmm where; lchownat fallback?]

It could be from lib/fchownat.c:106, if CHOWN_TRAILING_SLASH_BUG is 
defined. However, I'd be surprised if this were the case, as glibc 
doesn't have that bug as far as I know.

> 		lstat64
> 		fstatat64
> 	lchown <at> plt
> 		lchown
> 
> Thereafter only 10 "??" stepi in between resolved lchown and
> 
> 	lchmod <at> plt
> 		fchmodat
If 'cp' was linked correctly, I don't see any way there could be only 10 
insns between resolved lchown (presumably called from src/copy.c:3152 
via lib/openat.h:77) and any call to lchmod/fchmodat.




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Tue, 16 Sep 2025 19:22:02 GMT) Full text and rfc822 format available.

Message #56 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Steffen Nurpmeso <steffen <at> sdaoden.eu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Tue, 16 Sep 2025 12:21:46 -0700
On 2025-09-16 11:51, Steffen Nurpmeso wrote:
> I attach a tar archives of the two different logfiles, maybe some
> GNU build system guru can figure out more.

The first difference in those logs occurs when 'configure' compiles and 
run the following program. It should succeed (exit status 0) but in your 
fakeroot build it fails and 'configure' then assumes chown needs 
replacement. Can you figure out why the test program fails (exit status 
5) in the fakeroot environment? You can use strace to help find out. 
Once we figure this out, it may explain the other differences in the logs.

  #include <unistd.h>
  #include <stdlib.h>
  #include <errno.h>
  #include <fcntl.h>
  #include <sys/stat.h>

  int
  main (void)
  {
    struct stat st1, st2;
    if (close (creat ("conftest.file", 0600))) return 1;
    if (stat ("conftest.file", &st1)) return 2;
    sleep (1);
    if (chown ("conftest.file", st1.st_uid, st1.st_gid)) return 3;
    if (stat ("conftest.file", &st2)) return 4;
    if (st2.st_ctime <= st1.st_ctime) return 5;
  }

Here's what strace says on my Fedora 42 host:

  creat("conftest.file", 0600) = 3
  close(3) = 0
  newfstatat(AT_FDCWD, "conftest.file", {st_mode=S_IFREG|0600, 
st_size=0, ...}, 0) = 0
  clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=1, tv_nsec=0}, 
0x7fffc15bb1f0) = 0
  chown("conftest.file", 1000, 1000) = 0
  newfstatat(AT_FDCWD, "conftest.file", {st_mode=S_IFREG|0600, 
st_size=0, ...}, 0) = 0
  exit_group(0) = ?





Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Wed, 17 Sep 2025 16:47:01 GMT) Full text and rfc822 format available.

Message #59 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Wed, 17 Sep 2025 18:46:11 +0200
Hello.

Paul Eggert wrote in
 <c5312808-81e2-40b1-9069-cad8c5a79793 <at> cs.ucla.edu>:
 |On 2025-09-16 11:51, Steffen Nurpmeso wrote:
 |> I attach a tar archives of the two different logfiles, maybe some
 |> GNU build system guru can figure out more.
 |
 |The first difference in those logs occurs when 'configure' compiles and 
 |run the following program. It should succeed (exit status 0) but in your 

Sure.  (Just wondering, the final cp(1) should work for all
configurable cases if config succeeds; the bug report as such was
that "cp -a symlink symlink" causes a "set -e" build script to
fail due to the exit status.)

 |fakeroot build it fails and 'configure' then assumes chown needs 

fakeroot is btw

  Version:      1.37.1.2
  URL:          http://packages.debian.org/unstable/utils/fakeroot

 |replacement. Can you figure out why the test program fails (exit status 
 |5) in the fakeroot environment? You can use strace to help find out. 
 |Once we figure this out, it may explain the other differences in the logs.
 |
 |   #include <unistd.h>
 |   #include <stdlib.h>
 |   #include <errno.h>
 |   #include <fcntl.h>
 |   #include <sys/stat.h>
 |
 |   int
 |   main (void)
 |   {
 |     struct stat st1, st2;
 |     if (close (creat ("conftest.file", 0600))) return 1;
 |     if (stat ("conftest.file", &st1)) return 2;
 |     sleep (1);
 |     if (chown ("conftest.file", st1.st_uid, st1.st_gid)) return 3;
 |     if (stat ("conftest.file", &st2)) return 4;
 |     if (st2.st_ctime <= st1.st_ctime) return 5;
 |}
 |
 |Here's what strace says on my Fedora 42 host:
 |
 |   creat("conftest.file", 0600) = 3
 |   close(3) = 0
 |   newfstatat(AT_FDCWD, "conftest.file", {st_mode=S_IFREG|0600, 
 |st_size=0, ...}, 0) = 0
 |   clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=1, tv_nsec=0}, 
 |0x7fffc15bb1f0) = 0
 |   chown("conftest.file", 1000, 1000) = 0
 |   newfstatat(AT_FDCWD, "conftest.file", {st_mode=S_IFREG|0600, 
 |st_size=0, ...}, 0) = 0
 |   exit_group(0) = ?

But that is not via fakeroot?  I get the very result here.
With fakeroot, i have instrumented it, and the above:

       struct stat st1, st2;
       if (close (creat ("conftest.file", 0600))) return 1;
  fprintf(stderr, "AFTER CLOSE\n");
       if (stat ("conftest.file", &st1)) return 2;
  fprintf(stderr, "AFTER STAT\n");
       sleep (1);
       if (chown ("conftest.file", st1.st_uid, st1.st_gid)) return 3;
  fprintf(stderr, "AFTER CHOWN\n");
       if (stat ("conftest.file", &st2)) return 4;
  fprintf(stderr, "AFTER STAT 2\n");
       if (st2.st_ctime == st1.st_ctime) return 6;
       if (st2.st_ctime <= st1.st_ctime) return 5;
  fprintf(stderr, "AFTER TIMECMP\n");
  return 0;

and i show my complete prompt which includes $?

  AFTER CLOSE
  FAKEROOT: r=1092, received message type=1, message=3
  FAKEROOT: process stat oldstate=dev:ino=(21:285264), mode=0100600, own=(1000,1000), nlink=1, rdev=0
  FAKEROOT:    (previously unknown)
  AFTER STAT
  chown path conftest.file owner 0 group 0
       ==lchown -1 1 Operation not permitted
  FAKEROOT: r=1092, received message type=1, message=0
  AFTER CHOWN
  FAKEROOT: process chown dev:ino=(21:285264), mode=0100600, own=(0,0), nlink=1, rdev=0
  FAKEROOT: insert_or_overwrite unknown stat:
  dev:ino=(21:285264), mode=0100600, own=(0,0), nlink=1, rdev=0
  FAKEROOT: r=1092, received message type=1, message=3
  FAKEROOT: process stat oldstate=dev:ino=(21:285264), mode=0100600, own=(1000,1000), nlink=1, rdev=0
  FAKEROOT: (previously known): fake=dev:ino=(21:285264), mode=0100600, own=(0,0), nlink=1, rdev=0
  AFTER STAT 2
  #?6|kent:tmp$

So

  creat("conftest.file", 0600)            = 3
  close(3)                                = 0
  stat("conftest.file", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
  clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=1, tv_nsec=0}, 0x7ffeff1f6a10) = 0
  stat("conftest.file", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
  lchown("conftest.file", 0, 0)           = -1 EPERM (Operation not permitted)

Fakeroot fails to chown but ignores the error, yet the failed
system call avoids getting the filestamp updated.  Maybe fakeroot
should "simply" perform the task with the original user and group,
which are available, in order to make timestamp updates happen?

  #ifdef LIBFAKEROOT_DEBUGGING
    if (fakeroot_debug) {
      fprintf(stderr, "chown path %s owner %d group %d\n", path, owner, group);
    }
  #endif /* LIBFAKEROOT_DEBUGGING */
  #ifdef LCHOWN_SUPPORT
    /*chown(sym-link) works on the target of the symlink if lchown is
      present and enabled.*/
    r=INT_NEXT_STAT(path, &st);
  #else
    /*chown(sym-link) works on the symlink itself, use lstat: */
    r=INT_NEXT_LSTAT(path, &st);
  #endif

    if(r)
      return r;
    st.st_uid=owner;
    st.st_gid=group;
    INT_SEND_STAT(&st,chown_func);
    if(!dont_try_chown())
      r=next_lchown(path,owner,group);
    else
      r=0;
    if(r&&(errno==EPERM))
      r=0;

Would be a thing to protect against these conflicts.

Well, ok, this is a thing, fakeroot warns against using it when
running GNU autoconf systems, yet i use it to run the package
manager as such (;-}  Yeah, the problem is that the package
footprints are checked, and then owner/group mismatches kill.
Unfortunately the "make" and "make install" rules are run in
a single "build()" step by this package manager .. maybe one of
the very few not so nice decisions.

All i could do otherwise is UID mapping inside this "filesystem
overlay namespace container", but this is a hard thing to get
right .. if at all.  It has been around five years since i
created this environment for package building on this Linux
distro, yours is the first which fails.  I have forgotten why
i did not use UID mapping stuff.  It is also, maybe, that i do
*not* want to be root in the namespace.  One reason why i do not
use a VM, or LXC (or what its name was) or docker or all that.
Simple mostly read-only overlayfs that then hosts

        ip netns exec ${NETNS} \
                /usr/bin/env -i TERM=${TERM} \
                        /usr/bin/unshare --ipc --uts --pid --fork --mount --mount-proc ${kill_child} \
                                ${rooter} /init

where /init in this case effectively is

  ${SUPER} -u ports /usr/bin/nice -n +20 fakeroot pkgmk ""${@}

where $SUPER is doas(1) (or sudo or super that existed around Y2K
and has not seen for long even via Google).

Having said all that, and fakeroot aside, GNU cp(1) should not
exit error if it fails to preserve permissions for a symbolic link

  #?1|kent:tmp$ rm xc
  #?0|kent:tmp$ /bin/cp -a xb xc
  cp: failed to preserve ownership for xc: Operation not supported
  #?1|kent:tmp$ ls -l xa xb xc
  -rw-r----- 1 steffen steffen 0 Sep 16 19:48 xa
  lrwxrwxrwx 1 steffen steffen 2 Sep 17 18:44 xc -> xa
  lrwxrwxrwx 1 steffen steffen 2 Sep 16 19:48 xb -> xa

that way, so some fallback path in GNU coreutils is "bogus".

 --End of <c5312808-81e2-40b1-9069-cad8c5a79793 <at> cs.ucla.edu>

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Wed, 17 Sep 2025 17:27:01 GMT) Full text and rfc822 format available.

Message #62 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Wed, 17 Sep 2025 19:26:52 +0200
Steffen Nurpmeso wrote in
 <20250917164611.JO87MYf4 <at> steffen%sdaoden.eu>:
 ...
 |Fakeroot fails to chown but ignores the error, yet the failed
 |system call avoids getting the filestamp updated.  Maybe fakeroot
 |should "simply" perform the task with the original user and group,
 |which are available, in order to make timestamp updates happen?
 ...

i asked clint(AT)debian thus

  If intercepted system calls try to chown() to the very user and
  group that fakeroot reported that a file has, and the stat cache
  gives a hot entry for the file thus, wouldn't it make sense to
  assume that "something like the above" is the desire of the
  programmer?
  "Faking" the operation in such a context does not appear overly
  grazy to me?  What do you think?

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Thu, 18 Sep 2025 04:59:02 GMT) Full text and rfc822 format available.

Message #65 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Steffen Nurpmeso <steffen <at> sdaoden.eu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Wed, 17 Sep 2025 21:58:07 -0700
On 2025-09-17 09:46, Steffen Nurpmeso wrote:
> (Just wondering, the final cp(1) should work for all
> configurable cases if config succeeds;

That sounds pretty ambitious! The main goal here is merely for coreutils 
to work on practical platforms.

> But that is not via fakeroot?

No, I'm not using fakeroot. I don't recommend using fakeroot for 
'configure', for all the usual reasons.

> Fakeroot fails to chown but ignores the error, yet the failed
> system call avoids getting the filestamp updated.

Clearly a bug in fakeroot. POSIX says the file timestamp must be updated.

> i do
> *not* want to be root in the namespace.

That's fine. 'configure' need not be run as root. I don't recommend 
running it as root.

> Having said all that, and fakeroot aside, GNU cp(1) should not
> exit error if it fails to preserve permissions for a symbolic link

GNU cp does not try to change the permissions of a symlink.

>    #?0|kent:tmp$ /bin/cp -a xb xc
>    cp: failed to preserve ownership for xc: Operation not supported

That's not preserving permissions; it's preserving ownership. It's a 
different system call, with quite different semantics.





Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Thu, 18 Sep 2025 12:58:02 GMT) Full text and rfc822 format available.

Message #68 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Thu, 18 Sep 2025 14:57:10 +0200
Paul Eggert wrote in
 <cc4dea61-3ed8-4224-ab49-d48bb34af37a <at> cs.ucla.edu>:
 |On 2025-09-17 09:46, Steffen Nurpmeso wrote:
 |> (Just wondering, the final cp(1) should work for all
 |> configurable cases if config succeeds;
 |
 |That sounds pretty ambitious! The main goal here is merely for coreutils 
 |to work on practical platforms.

I think there are / have been filesystems with a time resolution
smaller than one second.

 ...
 |>    #?0|kent:tmp$ /bin/cp -a xb xc
 |>    cp: failed to preserve ownership for xc: Operation not supported
 |
 |That's not preserving permissions; it's preserving ownership. It's a 
 |different system call, with quite different semantics.

The GNU autoconf result of coreutils / cp results in a code
path that does not work the way it should.  That much is plain,
and that i reported.  I am not looking into GNU autoconf aka the
conclusions of GNU coreutils and the resulting coreutils / gnulib
/ GNU libc module / overlay / patchwork fusion which results.
Also since i went several times for you in the past and have been
dismissed drastically, just like again this time.

I also disagree with "practical platforms" given that the
effective log difference seems to be (from a diff(1) glance)

  +#define CHOWN_CHANGE_TIME_BUG 1
  +#define MKNOD_FIFO_BUG 1

The latter seems to come from

	configure:65539: checking whether mknod can create fifo without root privileges
	...
	configure:65580: $? = 99
	...
	| /* Indeterminate for super-user, assume no.  Why are you running
	|          configure as root, anyway?  */
	|       if (geteuid () == ROOT_UID) return 99;
	|       if (mknod ("conftest.fifo", S_IFIFO | 0600, 0)) return 2;
	|   ;
	|   return 0;
	| }
	configure:65601: result: no

Not a bug.
All in all the two above, plus some getgroups() difference should not result in
a disfunctional cp(1) i would think.

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)




Information forwarded to bug-coreutils <at> gnu.org:
bug#79433; Package coreutils. (Thu, 18 Sep 2025 14:38:02 GMT) Full text and rfc822 format available.

Message #71 received at 79433 <at> debbugs.gnu.org (full text, mbox):

From: Steffen Nurpmeso <steffen <at> sdaoden.eu>
To: Steffen Nurpmeso <steffen <at> sdaoden.eu>
Cc: Paul Eggert <eggert <at> cs.ucla.edu>, 79433 <at> debbugs.gnu.org
Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?
Date: Thu, 18 Sep 2025 16:36:57 +0200
Steffen Nurpmeso wrote in
 <20250918125710.WAELlo5o <at> steffen%sdaoden.eu>:

Sigh.
That build system is bogus anyhow, the manual pages are all
rebuild when i change a C source file?

  ...
 ||>    #?0|kent:tmp$ /bin/cp -a xb xc
 ||>    cp: failed to preserve ownership for xc: Operation not supported
 ...
 |I also disagree with "practical platforms" given that the
 |effective log difference seems to be (from a diff(1) glance)
 |
 |  +#define CHOWN_CHANGE_TIME_BUG 1
 |  +#define MKNOD_FIFO_BUG 1
 ...
 |All in all the [.] above [.] difference should not \
 |result in
 |a disfunctional cp(1) i would think.

I think i would possibly simply discard the return value of the
l?chmod() that is used in the fallback path.  The statement

          so we are required to update ctime.  Since lchown succeeded,
          we assume that lchmod will do likewise.  But if the system
          lacks lchmod and lutimes, we are out of luck.  Oh well.  */

seems a bit wacky given that there is NFS and fuse and maybe more,
and then this is inherently racy at first, and then updating the
ctime is not as "system-critical" as is the operation itself,
changing the owner, and that has already succeeded.  Thus i'd say

--- coreutils-9.7.old/lib/chown.c	2025-01-01 10:32:29.000000000 +0100
+++ coreutils-9.7/lib/chown.c	2025-09-18 16:32:00.535172071 +0200
@@ -130,7 +130,7 @@ rpl_chown (const char *file, uid_t uid,
          we assume that chmod will do likewise.  Fortunately, on all
          known systems where a 'no-op' chown skips the ctime update, a
          'no-op' chmod still does the trick.  */
-      result = chmod (file, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO
+      /*result =*/ chmod (file, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO
                                           | S_ISUID | S_ISGID | S_ISVTX));
     }
 # endif
--- coreutils-9.7.old/lib/lchown.c	2025-01-01 10:32:29.000000000 +0100
+++ coreutils-9.7/lib/lchown.c	2025-09-18 16:32:03.335172023 +0200
@@ -105,7 +105,7 @@ rpl_lchown (const char *file, uid_t uid,
          so we are required to update ctime.  Since lchown succeeded,
          we assume that lchmod will do likewise.  But if the system
          lacks lchmod and lutimes, we are out of luck.  Oh well.  */
-      result = lchmod (file, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO
+      /*result =*/ lchmod (file, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO
                                            | S_ISUID | S_ISGID | S_ISVTX));
     }
 # endif

Greetings,

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)




This bug report was last modified 1 day ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.