I have a program that loads a simple hello world binary into memory using memfd_create
and then writing the binary data to the file with write
. I then fork a process and call fexecve
.
The code works just fine and I get the usual "hello world" output that I am expecting when I run the program so I went and tested it with Valgrind to make sure there were no memory leaks as it's part of a larger project and got the following Valgrind output:
VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting.
valgrind: the 'impossible' happened:
Killed by fatal signal
at 0x495B178: fexecve
And no output from the hello_world program at all.
I've tried different exec-like functions that work on anonymous files such as fexecve(file_fd, argv, envp)
and execveat(file_fd, "", argv, envp, AT_EMPTY_PATH)
and all result in the same Valgrind segfault, but work properly without.
What's even more interesting though is that Valgrind chugs along happily if I use the classic execve("/path/to/hello_world", argv, envp)
. It reports no memory leaks and that the impossible did not, in fact, occur.
I am running valgrind 3.18.1 on an Ubuntu 22.04.3 vm.
This is probably the same thing as an issue I fixed last April. Try a more recent Valgrind.
commit 5f83395616befb96af66ec2cc7f4330605271faf
Author: Paul Floyd <redacted>
Date: Sun Apr 10 20:55:28 2022 +0200
Fix a crash handling fexecve.
Found this by testing the Solaris execx (the bits that are
Linux-compatible) test. That was giving
--28286-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--28286-- si_code=2; Faulting address: 0x4A0095A; sp: 0x1002ca9c88
valgrind: the 'impossible' happened:
Killed by fatal signal
host stacktrace:
==28286== at 0x5803DE54: vgPlain_strcpy (m_libcbase.c:309)
==28286== by 0x5810A9B3: vgSysWrap_linux_sys_execveat_before (syswrap-linux.c:13310)
==28286== by 0x580953C9: vgPlain_client_syscall (syswrap-main.c:2234)
It's a mistake to copy the path obtained with VG_(resolve_filename) to
the client ARG2, it's unlikely to have space for the path.
Instead just copy the pointer.