Subject: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?

From: Steffen Nurpmeso <[email-masked]>
Date: Sat, 13 Sep 2025 19:36:40 +0200

Paul Eggert wrote in
 <[email-masked]>:
 |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 <[email-masked]>

--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)