linux-user: openat2() bypasses absolute-path prefix rewriting under -L
## Host environment - Operating system: EndeavourOS x86_64 - OS/kernel version: Linux ArchLinux-desktop 6.19.6-arch1-1 #1 SMP PREEMPT_DYNAMIC Wed, 04 Mar 2026\ 18:25:08 +0000 x86_64 GNU/Linux\\ - Architecture: ALL - QEMU flavor: qemu-user(I tested qemu-x86_64 and riscv64) - QEMU version: 10.2.1 - QEMU command line: qemu-x86_64 -L /tmp/qemu-openat2-root /tmp/test-02 /tmp/qemu-openat2-check.txt ## Emulated/Virtualized environment QEMU-USER - Architecture:ALL ## Description of problem openat2() in linux-user appears to bypass the absolute-path prefix rewriting that openat() uses under -L or QEMU_LD_PREFIX. I can reproduce this locally with qemu-x86_64 10.2.1, and the source locations below match the 10.2.50 code layout. Relevant source locations: linux-user/syscall.c:8806 linux-user/syscall.c:8851 util/path.c:36 At linux-user/syscall.c:8806, openat() goes through path(pathname). At linux-user/syscall.c:8851, openat2() passes pathname directly to safe_openat2(). At util/path.c:36, path() only rewrites absolute paths. This creates a guest-visible split: openat("/tmp/file") resolves inside the configured guest prefix, while openat2("/tmp/file") still resolves against the host root. Observed output under qemu-x86_64 -L /tmp/qemu-openat2-root: openat ok "guest-file" openat2 ok "host-file" Expected behavior: openat() and openat2() should see the same guest-root-prefixed absolute path. Actual behavior: openat() opens the guest-root file, while openat2() opens the host-root file. This is a direct guest-visible filesystem semantic mismatch. ## Steps to reproduce 1. Minimal reproducer file: tests/02_openat2_prefix_escape.c(I upload it) [02_openat2_prefix_escape.c](/uploads/8450081e97d3d58dc08de17077c73dc7/02_openat2_prefix_escape.c) 2. Build it with `gcc -O2 -Wall -Wextra -static -o /tmp/test-02 tests/02_openat2_prefix_escape.c`. 3. Prepare the files with `mkdir -p /tmp/qemu-openat2-root/tmp`, `printf 'host-file\n' > /tmp/qemu-openat2-check.txt`, and `printf 'guest-file\n' > /tmp/qemu-openat2-root/tmp/qemu-openat2-check.txt`. 4. Run on native Linux with `/tmp/test-02 /tmp/qemu-openat2-check.txt`. 5. Run under QEMU without prefix rewriting using `qemu-x86_64 /tmp/test-02 /tmp/qemu-openat2-check.txt`. 6. Run under QEMU with prefix rewriting using `qemu-x86_64 -L /tmp/qemu-openat2-root /tmp/test-02 /tmp/qemu-openat2-check.txt`. 7. Compare the data returned by openat() and openat2(). ## Additional information I am a student from Xidian University. I quickly discovered some bugs through Codex. I know that QEMU does not accept content directly generated by AI, so I have verified them and confirm that this bug is **valid**. code: ```c #define _GNU_SOURCE #include <errno.h> #include <fcntl.h> #include <linux/openat2.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/syscall.h> #include <unistd.h> static void print_result(const char *tag, int fd) { char buf[128]; ssize_t n; if (fd < 0) { printf("%s errno=%d (%s)\n", tag, errno, strerror(errno)); return; } n = read(fd, buf, sizeof(buf) - 1); if (n < 0) { printf("%s read_errno=%d (%s)\n", tag, errno, strerror(errno)); close(fd); return; } buf[n] = '\0'; close(fd); printf("%s ok \"%s\"\n", tag, buf); } int main(int argc, char **argv) { struct open_how how; const char *path; int fd; if (argc != 2) { fprintf(stderr, "usage: %s <absolute-path>\n", argv[0]); return 2; } path = argv[1]; memset(&how, 0, sizeof(how)); how.flags = O_RDONLY; fd = openat(AT_FDCWD, path, O_RDONLY); print_result("openat", fd); fd = syscall(SYS_openat2, AT_FDCWD, path, &how, sizeof(how)); print_result("openat2", fd); return 0; } ```
issue