linux-user: Implement faccessat2

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>
This commit is contained in:
WANG Xuerui 2022-10-09 14:08:13 +08:00 committed by Laurent Vivier
parent ed98cdecf8
commit 35a2c85f7d
3 changed files with 13 additions and 1 deletions

View 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,

View file

@ -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
#ifdef TARGET_NR_fadvise64
{ TARGET_NR_fadvise64, "fadvise64" , NULL, NULL, NULL },
#endif

View 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));