Subject: bug#65599: mv and cp give a pointless warning when moving/copying a directory

From: Bruno Haible <[email-masked]>
Date: Fri, 01 Sep 2023 17:09:20 +0200

Paul Eggert wrote:
> it'd be helpful to know whether the bug is limited to fchownat or 
> (as I suspect) applies also to the other chown variants. Could you try 
> running the attached program on your platform, to see whether the bug 
> affects these other variants?

It applies to all 4 variants, as can be seen from applying it to a directory:

$ ./a.out /media/nas/bruno/dir1
lchown: Permission denied
fchownat: Permission denied
chown: Permission denied
fchown: Permission denied

$ strace ./a.out /media/nas/bruno/dir1
...
lchown("/media/nas/bruno/dir1", 1000, 1000) = -1 EACCES (Permission denied)
dup(2)                                  = 3
fcntl(3, F_GETFL)                       = 0x2 (flags O_RDWR)
getrandom("\x31\xd2\xe1\x4b\xa3\xa9\x0a\x95", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x56031b7c9000
brk(0x56031b7ea000)                     = 0x56031b7ea000
newfstatat(3, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x9), ...}, AT_EMPTY_PATH) = 0
write(3, "lchown: Permission denied\n", 26lchown: Permission denied
) = 26
close(3)                                = 0
fchownat(AT_FDCWD, "/media/nas/bruno/dir1", 1000, 1000, AT_SYMLINK_NOFOLLOW) = -1 EACCES (Permission denied)
dup(2)                                  = 3
fcntl(3, F_GETFL)                       = 0x2 (flags O_RDWR)
newfstatat(3, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x9), ...}, AT_EMPTY_PATH) = 0
write(3, "fchownat: Permission denied\n", 28fchownat: Permission denied
) = 28
close(3)                                = 0
chown("/media/nas/bruno/dir1", 1000, 1000) = -1 EACCES (Permission denied)
dup(2)                                  = 3
fcntl(3, F_GETFL)                       = 0x2 (flags O_RDWR)
newfstatat(3, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x9), ...}, AT_EMPTY_PATH) = 0
write(3, "chown: Permission denied\n", 25chown: Permission denied
) = 25
close(3)                                = 0
openat(AT_FDCWD, "/media/nas/bruno/dir1", O_RDONLY|O_NOFOLLOW) = 3
fchown(3, 1000, 1000)                   = -1 EACCES (Permission denied)
dup(2)                                  = 4
fcntl(4, F_GETFL)                       = 0x2 (flags O_RDWR)
newfstatat(4, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x9), ...}, AT_EMPTY_PATH) = 0
write(4, "fchown: Permission denied\n", 26fchown: Permission denied
) = 26
close(4)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++

or to a regular file:

$ ./a.out /media/nas/bruno/dir1/file1 
lchown: Permission denied
fchownat: Permission denied
chown: Permission denied
fchown: Permission denied

$ strace ./a.out /media/nas/bruno/dir1/file1 
...
lchown("/media/nas/bruno/dir1/file1", 1000, 1000) = -1 EACCES (Permission denied)
dup(2)                                  = 3
fcntl(3, F_GETFL)                       = 0x2 (flags O_RDWR)
getrandom("\x59\x38\xf4\xfa\x24\xc4\x89\x64", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x56337cdfa000
brk(0x56337ce1b000)                     = 0x56337ce1b000
newfstatat(3, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x9), ...}, AT_EMPTY_PATH) = 0
write(3, "lchown: Permission denied\n", 26lchown: Permission denied
) = 26
close(3)                                = 0
fchownat(AT_FDCWD, "/media/nas/bruno/dir1/file1", 1000, 1000, AT_SYMLINK_NOFOLLOW) = -1 EACCES (Permission denied)
dup(2)                                  = 3
fcntl(3, F_GETFL)                       = 0x2 (flags O_RDWR)
newfstatat(3, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x9), ...}, AT_EMPTY_PATH) = 0
write(3, "fchownat: Permission denied\n", 28fchownat: Permission denied
) = 28
close(3)                                = 0
chown("/media/nas/bruno/dir1/file1", 1000, 1000) = -1 EACCES (Permission denied)
dup(2)                                  = 3
fcntl(3, F_GETFL)                       = 0x2 (flags O_RDWR)
newfstatat(3, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x9), ...}, AT_EMPTY_PATH) = 0
write(3, "chown: Permission denied\n", 25chown: Permission denied
) = 25
close(3)                                = 0
openat(AT_FDCWD, "/media/nas/bruno/dir1/file1", O_RDONLY|O_NOFOLLOW) = 3
fchown(3, 1000, 1000)                   = -1 EACCES (Permission denied)
dup(2)                                  = 4
fcntl(4, F_GETFL)                       = 0x2 (flags O_RDWR)
newfstatat(4, "", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x9), ...}, AT_EMPTY_PATH) = 0
write(4, "fchown: Permission denied\n", 26fchown: Permission denied
) = 26
close(4)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++

> Also, could you let us know the kernel and glibc version? The bug should 
> be documented in gnulib/doc, I'd think. (Plus, reported to the Linux 
> and/or glibc maintainers....)

$ uname -srv
Linux 5.15.0-79-generic #86-Ubuntu SMP Mon Jul 10 16:07:21 UTC 2023
$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.35-0ubuntu3.1) stable release version 2.35.
...

Bruno