我有一个程序,使用
memfd_create
将简单的 hello world 二进制文件加载到内存中,然后使用 write
将二进制数据写入文件。然后我分叉一个进程并调用 fexecve
。
代码工作得很好,当我运行程序时,我得到了我所期待的通常的“hello world”输出,所以我用 Valgrind 对其进行了测试,以确保没有内存泄漏,因为它是一个更大项目的一部分,并得到了以下 Valgrind 输出:
VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting.
valgrind: the 'impossible' happened:
Killed by fatal signal
at 0x495B178: fexecve
hello_world 程序根本没有输出。
我尝试过不同的类似 exec 的函数,这些函数适用于匿名文件,例如
fexecve(file_fd, argv, envp)
和 execveat(file_fd, "", argv, envp, AT_EMPTY_PATH)
,并且所有结果都会导致相同的 Valgrind 段错误,但无需使用即可正常工作。
更有趣的是,如果我使用经典的
execve("/path/to/hello_world", argv, envp)
,Valgrind 会愉快地前进。它报告没有内存泄漏,而且事实上不可能的事情并没有发生。
这可能与我去年四月修复的问题相同。尝试更新的 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-cmpatible) 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.