Search code examples
cexecvalgrind

Valgrind is reporting the Impossible happened using an fexecve call


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.


Solution

  • 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.