Bug 496353

Summary: Valgrind wrapper of execveat always returns ENOENT with memfd
Product: [Developer tools] valgrind Reporter: freenullptr
Component: generalAssignee: Julian Seward <jseward>
Status: REPORTED ---    
Severity: normal    
Priority: NOR    
Version First Reported In: 3.24 GIT   
Target Milestone: ---   
Platform: Arch Linux   
OS: Linux   
Latest Commit: Version Fixed/Implemented In:
Sentry Crash Report:
Attachments: Minimal test case to reproduce the issue.

Description freenullptr 2024-11-16 16:56:43 UTC
Created attachment 175863 [details]
Minimal test case to reproduce the issue.

SUMMARY
Using memfd_create(2), one can create an anonymous file and retrieve its file descriptor. The fexecve(3) function can be used to execute such a file. This combination of functions can be used to execute a program from memory.
The fexecve function is implemented in glibc on Linux through the execveat(2) syscall. When running under Valgrind, execveat errorneously always fails with errno set to ENOENT when a file descriptor retrieved from memfd_create is passed to it.
This is causedf by the fact that the execveat wrapper constructs an absolute path to the file pointed to by dirfd (or dirfd and pathname). For memfd files, procfs returns the path as /memfd:NAME (deleted), a bogus path to a file that almost certainly doesn't exist. This path is ultimately passed to execve, which fails to open the file.

STEPS TO REPRODUCE
1. Extract the attachment valgrind-fexecve.zip.
2. Execute `make`. This requires a C compiler and xxd.
3. Execute `broken` normally to observe correct results and run it under Valgrind to reproduce the issue.

OBSERVED RESULT
The program prints the error "fexecve failed: No such file or directory" and exits with an exit code of 1.

EXPECTED RESULT
The program prints `Hello from embedded executable` and exits succesfully.

SOFTWARE/OS VERSIONS
Linux: 6.11.5