ppc: 0.875 user-level: 0.816 x86: 0.800 architecture: 0.741 graphic: 0.708 device: 0.635 peripherals: 0.591 virtual: 0.534 kernel: 0.527 performance: 0.508 arm: 0.504 semantic: 0.493 debug: 0.488 PID: 0.407 vnc: 0.388 files: 0.370 register: 0.312 permissions: 0.285 network: 0.231 TCG: 0.190 socket: 0.181 mistranslation: 0.166 VMM: 0.159 hypervisor: 0.142 risc-v: 0.127 assembly: 0.124 boot: 0.120 i386: 0.092 KVM: 0.042 -------------------- user-level: 0.972 x86: 0.649 debug: 0.562 virtual: 0.521 files: 0.074 TCG: 0.049 PID: 0.020 register: 0.016 arm: 0.014 kernel: 0.013 network: 0.008 permissions: 0.007 semantic: 0.007 hypervisor: 0.006 performance: 0.005 device: 0.005 architecture: 0.004 VMM: 0.004 ppc: 0.004 boot: 0.003 socket: 0.002 peripherals: 0.002 graphic: 0.001 i386: 0.001 assembly: 0.001 vnc: 0.001 KVM: 0.000 mistranslation: 0.000 risc-v: 0.000 linux-user: openat on /proc/self/exe can return a closed file descriptor Description of problem: `open("/proc/self/exe", ...)` returns a closed file descriptor if qemu-user was executed as an interpreter, passing a file descriptor in the `AT_EXECFD` auxval. When the `AT_EXECFD` auxval is nonzero the user program is loaded through `load_elf_binary()` (in `linux-user/elfload.c`) which ultimately calls `load_elf_image()` with that same file descriptor, and `load_elf_image()` closes the file descriptor before returning. `do_openat` in `linux-user/syscall.c` will return that file descriptor to the user if the opened path satisfies `is_proc_myself(pathname, "exe")`, which is obviously wrong both in that the file descriptor is closed as part of the initialization process of qemu itself, and that the user program would then close that file descriptor and thus the next invocation of `open` would have the same problem. Steps to reproduce: This program prints `3 3` in a x86_64 docker container on my machine (arm64 macos, which docker desktop handles by running containers in a native linux VM under qemu-user). ```c #include #include int main(int argc, char **argv) { int selfexe = open("/proc/self/exe", O_RDONLY | O_CLOEXEC); if (selfexe < 0) { perror("open self"); return 1; } int devnull = open("/dev/null", O_WRONLY | O_CLOEXEC); if (devnull < 0) { perror("open devnull"); return 1; } printf("%d %d\n", selfexe, devnull); } ``` Additional information: Thanks to @pm215 for helping me pinpoint the exact issue I was encountering.