Hi,

Quoting Johannes Schauer Marin Rodrigues (2023-02-06 00:47:35)
> since glibc 2.34 and coreutils 9.1, fakeroot fails to preserve ownership
> information when running "cp -a" on a file owned by a user other than
> root. On armel, armhf and i386 (our 32 bit arches), you can reproduce
> this problem by running inside fakeroot:
> 
> $ touch foo
> $ chown 0:42 foo
> $ ls -lha foo
> $ cp -a foo bar
> $ ls -lha bar"
> 
> which will print this:
> 
> -rw-r--r-- 1 root shadow 0 Feb  5 23:00 foo
> -rw-r--r-- 1 root root 0 Feb  5 23:00 bar
> 
> I submitted an improvement to the `cp-a` test which adds a check for the
> ownership information in addition to the mode checks as a merge request
> for that test here:
> 
> https://salsa.debian.org/clint/fakeroot/-/merge_requests/19
> 
> Observe how the salsaci pipeline succeds for amd64 but fails on i386.
> The reason is that on i386, fakeroot will not retain the ownership
> information.
> 
> A quick comparison of the strace output on arm64 (which does not have
> this problem) and armhf (which does have this problem) shows that arm64
> calls fchown() while armhf calls fchown32() which is not wrapped by
> fakeroot. Maybe that is the problem?
> 
> This breaks my package mmdebstrap in a similar way as #1023286 did.

I have a little bit of more input. This is what "cp --preserve=ownership" does
on amd64 (according to ltrace):

open("bar", 2162688, 015412541474)                                              
          = -1
__errno_location()                                                              
          = 0x7ff47c598398
fstatat(0xffffff9c, 0x7ffe6c2ac337, 0x7ffe6c2aae10, 0)                          
          = 0
open("foo", 0, 00)                                                              
          = 3
fstat(3, 0x7ffe6c2aafc0, 0, 0x7ff47c72ae51)                                     
          = 0
openat(0xffffff9c, 0x7ffe6c2ac33b, 193, 384)                                    
          = 4
__errno_location()                                                              
          = 0x7ff47c598398
ioctl(4, 1074041865, 0x3)                                                       
          = -1
fstat(4, 0x7ffe6c2aaf30, 0xffffffff, 0x7ff47c730bab)                            
          = 0

Okay, nothing to see here. This works, after all. On i386 it looks like this:

open64("bar", 2162688, 012625311011)                                            
          = -1
__errno_location()                                                              
          = 0xf7bf56bc
__fstatat64_time64(-100, 0xff958337, 0xff957948, 0)                             
          = 0
open64("foo", 0, 00)                                                            
          = 3
__fstat64_time64(3, 0xff957a8c, 0xff957948, 0)                                  
          = 0
openat64(-100, 0xff95833b, 193, 384)                                            
          = 4
__errno_location()                                                              
          = 0xf7bf56bc
__ioctl_time64(4, 0x40049409, 3, 1)                                             
          = -1
__fstat64_time64(4, 0xff957a20, 0, 0)                                           
          = 0

So now this looks even more like #1023286 because it involves
__fstatat64_time64 and __fstat64_time64. I added this patch to fakeroot:

--- a/libfakeroot.c
+++ b/libfakeroot.c
@@ -2671,6 +2673,11 @@ int WRAP_FSTATAT64_TIME64 FSTATAT64_TIME64_ARG(int ver,

   int r;

+#ifdef LIBFAKEROOT_DEBUGGING
+  if (fakeroot_debug) {
+    fprintf(stderr, "fstatat64[time64] fd %d %s\n", dir_fd, path);
+  }
+#endif /* LIBFAKEROOT_DEBUGGING */
   r=NEXT_FSTATAT64_TIME64(ver, dir_fd, path, st, flags);
   if(r)
     return -1;

And re-ran the t.cp-a test that I changed according to my merge request to
reproduce the problem on i386 like this:

env --chdir=test srcdir=$(pwd)/test VERBOSE=1 libfakeroot=libfakeroot-0.so sh 
-x ./t.cp-a

(is there a better way to run individual tests with maximum verbosity?)

The relevant call to `cp -a` looks like this:

stat64 file_name /home/josch/usr/bin/cp
stat64 file_name /usr/local/bin/cp
stat64 file_name /usr/bin/cp
fstatat64[time64] fd -100 empty
load_library_symbols
fstat64[time64] fd 3
fstat64[time64] fd 4
flistxattr fd 3
flistxattr fd 3
fchmod fd 4

This seems to indicate that __fstatat64_time64 does get wrapped as expected.
The dirfd is set to -100 which is the special value AT_FDCWD.

I'm at a loss at how to proceed.

Can you find out more?

Thanks!

cheers, josch

Attachment: signature.asc
Description: signature

Reply via email to