X-Debbugs-Cc: z...@debian.org, cl...@debian.org, jo...@debian.org

Hi,

I've debugged it as well and here is my write up. Though I don't have solution
yet.

I use an i386 VM for testing and following code to simplify my test.

```c
int main() {
 struct stat buf;
 int r;
 r = fstatat(AT_FDCWD, "./test.c", &buf, 0);
 printf("%d %d %d\n", r, buf.st_ino, buf.st_gid);
}
```

Compile it with:

$ gcc -g -D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64 ./test.c

This same as coreutils that enables time64 support.

with the instruction in DEBUG file:

$ gdb ./a.out
(gdb) set env FAKEROOTKEY=430935964
(gdb) set env LD_PRELOAD=./prefix/lib/libfakeroot-0.so
(gdb) b main
Breakpoint 1 at 0x11b6: file ./test.c, line 10.
(gdb) r
Starting program: /home/debian/a.out 
Breakpoint 1, main () at ./test.c:10
10       r = fstatat(AT_FDCWD, "./test.c", &buf, 0);
(gdb) s
__fstatat64_time64 (dir_fd=-100, path=0x402008 "./test.c", st=0xbffff4d0, 
flags=0) at libfakeroot.c:2700
2700      r=NEXT_FSTATAT64_TIME64(ver, dir_fd, path, st, flags);
(gdb) p st
$1 = (struct stat64 *) 0xbffff4d0
(gdb) p *st
$2 = {st_dev = 11676941228, __pad1 = 3086760800, __st_ino = 1, st_mode = 0, 
st_nlink = 1, st_uid = 3087006272, st_gid = 0, st_rdev = 13257672154138279935, 
__pad2 = 3087005192, 
  st_size = -5188164414456463360, st_blksize = 44, st_blocks = 
-4611686117211635712, st_atim = {tv_sec = -1208183472, tv_nsec = 0}, st_mtim = 
{tv_sec = -1210426833, 
    tv_nsec = -1208328120}, st_ctim = {tv_sec = -1208207344, tv_nsec = 
-1208108853}, st_ino = 13257533047527070255}
(gdb) n
2701      if(r)
(gdb) p *st
$3 = {st_dev = 2049, __pad1 = 262484, __st_ino = 0, st_mode = 33188, st_nlink = 
1, st_uid = 1000, st_gid = 1000, st_rdev = 0, __pad2 = 221, st_size = 
17592186044416, st_blksize = 8, 
  st_blocks = 7205240262505791488, st_atim = {tv_sec = 0, tv_nsec = 296000000}, 
st_mtim = {tv_sec = 0, tv_nsec = 1677600726}, st_ctim = {tv_sec = 0, tv_nsec = 
92000000}, 
  st_ino = 7205240253915856896}
(gdb) p (struct __stat64_t64)(*st)
$4 = {st_dev = 2049, st_ino = 262484, st_mode = 33188, st_nlink = 1, st_uid = 
1000, st_gid = 1000, st_rdev = 0, st_size = 221, st_blksize = 4096, st_blocks = 
8, st_atim = {
    tv_sec = 1677600728, tv_nsec = 296000000}, st_mtim = {tv_sec = 1677600726, 
tv_nsec = 92000000}, st_ctim = {tv_sec = 1677600726, tv_nsec = 108000000}}

We can see that st struct is decoded into a wrong layout.
It causes the message passed to faked has wrong inode.

To verify the guess, I use following dirty patch,

>From ea3eab6ea82604f9a16d658f7fc7ec5ce4bc337d Mon Sep 17 00:00:00 2001
From: Shengjing Zhu <z...@debian.org>
Date: Wed, 1 Mar 2023 13:21:25 +0800
Subject: [PATCH] hack

---
 communicate.c | 35 +++++++++++++++++++++++++++++++++++
 communicate.h |  1 +
 libfakeroot.c |  9 +++++++--
 stat64.h      | 15 +++++++++++++++
 4 files changed, 58 insertions(+), 2 deletions(-)
 create mode 100644 stat64.h

diff --git a/communicate.c b/communicate.c
index dec9cc6..f7bbaf4 100644
--- a/communicate.c
+++ b/communicate.c
@@ -63,6 +63,8 @@
 #include "stats.h"
 #endif
 
+#include "stat64.h"
+
 #ifndef _UTSNAME_LENGTH
 /* for LINUX libc5 */
 #  define _UTSNAME_LENGTH _SYS_NMLN
@@ -864,6 +866,39 @@ void send_get_stat64(struct stat64 *st
   }
 }
 
+void send_get_stat64_2(struct stat64 *st)
+{
+  struct fake_msg buf;
+
+#ifndef FAKEROOT_FAKENET
+  if(init_get_msg()!=-1)
+#endif /* ! FAKEROOT_FAKENET */
+  {
+  buf.st.mode =((struct x__stat64 *)st)->st_mode;
+  buf.st.ino  =((struct x__stat64 *)st)->st_ino ;
+  buf.st.uid  =((struct x__stat64 *)st)->st_uid ;
+  buf.st.gid  =((struct x__stat64 *)st)->st_gid ;
+  buf.st.dev  =((struct x__stat64 *)st)->st_dev ;
+  buf.st.rdev =((struct x__stat64 *)st)->st_rdev;
+  buf.st.nlink=((struct x__stat64 *)st)->st_nlink;
+
+  fprintf(stderr, "libfakeroot: before ino %ld uid %ld gid %ld \n", 
buf.st.ino, buf.st.uid, buf.st.gid);
+
+    buf.id=stat_func;
+    send_get_fakem(&buf);
+
+
+  ((struct x__stat64 *)st)->st_mode =buf.st.mode;
+  ((struct x__stat64 *)st)->st_ino  =buf.st.ino ;
+  ((struct x__stat64 *)st)->st_uid  =buf.st.uid ;
+  ((struct x__stat64 *)st)->st_gid  =buf.st.gid ;
+  ((struct x__stat64 *)st)->st_dev  =buf.st.dev ;
+  ((struct x__stat64 *)st)->st_rdev =buf.st.rdev;
+
+  fprintf(stderr, "libfakeroot: after ino %ld uid %ld gid %ld \n", buf.st.ino, 
buf.st.uid, buf.st.gid);
+  }
+}
+
 void send_get_xattr64(struct stat64 *st
                , xattr_args *xattr
 #ifdef STUPID_ALPHA_HACK
diff --git a/communicate.h b/communicate.h
index a586108..5562402 100644
--- a/communicate.h
+++ b/communicate.h
@@ -211,6 +211,7 @@ extern void unlock_comm_sd(void);
 #ifndef STUPID_ALPHA_HACK
 extern void send_stat64(const struct stat64 *st, func_id_t f);
 extern void send_get_stat64(struct stat64 *buf);
+extern void send_get_stat64_2(struct stat64 *buf);
 extern void send_get_xattr64(struct stat64 *st, xattr_args *xattr);
 #else
 extern void send_stat64(const struct stat64 *st, func_id_t f, int ver);
diff --git a/libfakeroot.c b/libfakeroot.c
index 26a3e90..5eb35b3 100644
--- a/libfakeroot.c
+++ b/libfakeroot.c
@@ -2684,7 +2684,7 @@ int WRAP_FSTAT64_TIME64 FSTAT64_TIME64_ARG(int ver,
   r=NEXT_FSTAT64_TIME64(ver, fd, st);
   if(r)
     return -1;
-  SEND_GET_STAT64(st,ver);
+  send_get_stat64_2(st);
   return 0;
 }
 
@@ -2696,11 +2696,16 @@ int WRAP_FSTATAT64_TIME64 FSTATAT64_TIME64_ARG(int ver,
 
 
   int r;
+#ifdef LIBFAKEROOT_DEBUGGING
+  if (fakeroot_debug) {
+    fprintf(stderr, "fstatat64[time64] path %s\n", path);
+  }
+#endif /* LIBFAKEROOT_DEBUGGING */
 
   r=NEXT_FSTATAT64_TIME64(ver, dir_fd, path, st, flags);
   if(r)
     return -1;
-  SEND_GET_STAT64(st,ver);
+  send_get_stat64_2(st);
   return 0;
 }
 
diff --git a/stat64.h b/stat64.h
new file mode 100644
index 0000000..1cdaef3
--- /dev/null
+++ b/stat64.h
@@ -0,0 +1,15 @@
+#ifndef FAKEROOT_STAT64_H
+#define FAKEROOT_STAT64_H
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+struct x__stat64 {
+    dev_t     st_dev;     /* ID of device containing file */
+    ino64_t     st_ino;     /* inode number */
+    mode_t    st_mode;    /* protection */
+    nlink_t   st_nlink;   /* number of hard links */
+    uid_t     st_uid;     /* user ID of owner */
+    gid_t     st_gid;     /* group ID of owner */
+    dev_t     st_rdev;    /* device ID (if special file) */
+};
+#endif
-- 
2.39.2


With the new stat64 struct, at least the tests in fakeroot have passed on i386.

Now I'm not sure how to do right. At fakeroot, we don't know if the caller is
compiled with D_TIME_BITS=64 or not, so we don't know which stat64 struct to
use to decode the message.

Should we revert all packages that have compiled with D_TIME_BITS=64?

-- 
Regards,
Shengjing Zhu

Reply via email to