linux-user: Implement faccessat2
authorWANG Xuerui <xen0n@gentoo.org>
Sun, 9 Oct 2022 06:08:13 +0000 (14:08 +0800)
committerLaurent Vivier <laurent@vivier.eu>
Fri, 21 Oct 2022 15:46:19 +0000 (17:46 +0200)
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 <dilfridge@gentoo.org>
Signed-off-by: WANG Xuerui <xen0n@gentoo.org>
Message-Id: <20221009060813.2289077-1-xen0n@gentoo.org>
[lv: removing defined(__NR_faccessat2) in syscall.c,
     adding defined(TARGET_NR_faccessat2) on print_faccessat()]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
linux-user/strace.c
linux-user/strace.list
linux-user/syscall.c

index 86c081c83f744404b86172eaa87c3e034b3e5a1e..9ae5a812cd719e68f72a45881f5fc9c5dabc876d 100644 (file)
@@ -1969,7 +1969,7 @@ print_execv(CPUArchState *cpu_env, const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_faccessat
+#if defined(TARGET_NR_faccessat) || defined(TARGET_NR_faccessat2)
 static void
 print_faccessat(CPUArchState *cpu_env, const struct syscallname *name,
                 abi_long arg0, abi_long arg1, abi_long arg2,
index a87415bf3d50626468468d852710983969f37431..3df2184580aac8ac835efa11d4624c4c79c0f566 100644 (file)
 #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
 #ifdef TARGET_NR_fadvise64
 { TARGET_NR_fadvise64, "fadvise64" , NULL, NULL, NULL },
 #endif
index d499cac1d5d1b975be077951c31c18c03fc8d6d9..e985ad167f2123339b9a10476f436ee1c66dc16f 100644 (file)
@@ -9143,6 +9143,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)
+    case TARGET_NR_faccessat2:
+        if (!(p = lock_user_string(arg2))) {
+            return -TARGET_EFAULT;
+        }
+        ret = get_errno(faccessat(arg1, p, arg3, arg4));
+        unlock_user(p, arg2, 0);
+        return ret;
+#endif
 #ifdef TARGET_NR_nice /* not on alpha */
     case TARGET_NR_nice:
         return get_errno(nice(arg1));