From: Sun Haoyu <[email protected]> openat2() ignored the -L prefix and opened host files directly. For example, openat2("/tmp/file") opened /tmp/file on the host, not QEMU_LD_PREFIX/tmp/file like openat() does.
Fix this by using path() to rewrite absolute paths. Skip this when RESOLVE_BENEATH or RESOLVE_IN_ROOT is set: - RESOLVE_BENEATH rejects absolute paths anyway - RESOLVE_IN_ROOT resolves relative to dirfd Now openat() and openat2() work in the same way. Link: https://gitlab.com/qemu-project/qemu/-/work_items/3341 Signed-off-by: Sun Haoyu <[email protected]> Reviewed-by: Peter Maydell <[email protected]> Message-id: [email protected] Signed-off-by: Peter Maydell <[email protected]> (cherry picked from commit fa6dfcc373c244a767be04d236e0cdd075b80e69) Signed-off-by: Michael Tokarev <[email protected]> diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 44675076ca..f2c8037356 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8723,7 +8723,16 @@ static int do_openat2(CPUArchState *cpu_env, abi_long dirfd, if (fd > -2) { ret = get_errno(fd); } else { - ret = get_errno(safe_openat2(dirfd, pathname, &how, + const char *host_pathname = pathname; + if (pathname[0] == '/' && + !(how.resolve & (RESOLVE_IN_ROOT | RESOLVE_BENEATH))) { + /* + * RESOLVE_BENEATH rejects absolute paths; RESOLVE_IN_ROOT + * resolves them relative to dirfd. + */ + host_pathname = path(pathname); + } + ret = get_errno(safe_openat2(dirfd, host_pathname, &how, sizeof(struct open_how_ver0))); } diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 5d22759992..b5a2ad3b2d 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2771,7 +2771,12 @@ struct target_open_how_ver0 { #ifndef RESOLVE_NO_SYMLINKS #define RESOLVE_NO_SYMLINKS 0x04 #endif - +#ifndef RESOLVE_BENEATH +#define RESOLVE_BENEATH 0x08 +#endif +#ifndef RESOLVE_IN_ROOT +#define RESOLVE_IN_ROOT 0x10 +#endif #if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \ (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \ defined(TARGET_M68K) || defined(TARGET_MICROBLAZE) || \ -- 2.47.3
