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

From: Steffen Nurpmeso <[email-masked]>
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@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)