On 10/9/22 08:08, WANG Xuerui wrote:
User space has been preferring this syscall for a while, due to its
closer match with C semantics, and newer platforms such as LoongArch
apparently have libc implementations that don't fallback to faccessat
so normal access checks are failing without the emulation in place.

Tested by successfully emerging several packages within a Gentoo loong
stage3 chroot, emulated on amd64 with help of static qemu-loongarch64.

Reported-by: Andreas K. Hüttel <dilfri...@gentoo.org>
Signed-off-by: WANG Xuerui <xe...@gentoo.org>
---
  linux-user/strace.list | 3 +++
  linux-user/syscall.c   | 9 +++++++++
  2 files changed, 12 insertions(+)

There were two similar approaches from Richard and me:
https://lore.kernel.org/qemu-devel/20220729201414.29869-1-richard.hender...@linaro.org/#t
and
https://lore.kernel.org/qemu-devel/YzLdcnL6x646T61W@p100/

diff --git a/linux-user/strace.list b/linux-user/strace.list
index a87415bf3d..3df2184580 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -178,6 +178,9 @@
  #ifdef TARGET_NR_faccessat
  { TARGET_NR_faccessat, "faccessat" , NULL, print_faccessat, NULL },
  #endif
+#ifdef TARGET_NR_faccessat2
+{ TARGET_NR_faccessat2, "faccessat2" , NULL, print_faccessat, NULL },
+#endif

You are missing that part (from my patch):

--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1931,7 +1931,7 @@ print_execv(CPUArchState *cpu_env, const struct 
syscallname *name,
 }
 #endif

-#ifdef TARGET_NR_faccessat
+#if defined(TARGET_NR_faccessat) || defined(TARGET_NR_faccessat2)

otherwise if TARGET_NR_faccessat isn't defined, you won't have
the function print_faccessat() in strace.c defined.


  #ifdef TARGET_NR_fadvise64
  { TARGET_NR_fadvise64, "fadvise64" , NULL, NULL, NULL },
  #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 2e954d8dbd..a81f0b65b9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -9110,6 +9110,15 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int 
num, abi_long arg1,
          unlock_user(p, arg2, 0);
          return ret;
  #endif
+#if defined(TARGET_NR_faccessat2) && defined(__NR_faccessat2)
+    case TARGET_NR_faccessat2:
+        if (!(p = lock_user_string(arg2))) {
+            return -TARGET_EFAULT;
+        }
+        ret = get_errno(faccessat(arg1, p, arg3, arg4));

You rely here on the libc faccessat() function to either use
faccessat2() or faccessat() syscalls - which is probably the
best way around...

Helge

+        unlock_user(p, arg2, 0);
+        return ret;
+#endif
  #ifdef TARGET_NR_nice /* not on alpha */
      case TARGET_NR_nice:
          return get_errno(nice(arg1));


Reply via email to