mirror of
https://github.com/Mbed-TLS/mbedtls-framework.git
synced 2026-06-05 21:15:09 +00:00
Work around Valgrind hooking into _exit()
When running tests that use mbedtls_test_fork_run_child() under Valgrind, bad things happen. Specifically: * Valgrind reports leaks in the child. Those leaks do exist, but they're deliberate since we avoid cleaning up in the child (because we want to do as little as possible in the child, and because cleanups such as destroying PSA persistent keys would have undesirable effects outside the child process). * Valgrind's overridden `_exit()` doesn't just perform checks, but also for some reason it causes the file description on the .datax file to seek backwards, causing tests to run again in a loop. Avoid this by calling `execve()` (via `execlp()`) rather than `_exit()` if it looks like the test is run under Valgrind. This is safe as long as Valgrind isn't run with `--trace-children=yes`. Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
@@ -16,7 +16,9 @@
|
||||
|
||||
#include <test/fork_helpers.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
@@ -40,6 +42,27 @@ typedef enum {
|
||||
CHILD_EXIT_CODE_REPORTING_FAILED = 122,
|
||||
} child_exit_code_t;
|
||||
|
||||
static int env_contains_substring(const char *name, const char *substring)
|
||||
{
|
||||
const char *value = getenv(name);
|
||||
if (value == NULL) {
|
||||
return 0;
|
||||
} else {
|
||||
return strstr(value, substring) != NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int probably_running_under_valgrind(void)
|
||||
{
|
||||
if (env_contains_substring("LD_PRELOAD", "/vgpreload_")) {
|
||||
return 1;
|
||||
}
|
||||
if (env_contains_substring("DYLD_INSERT_LIBRARIES", "/vgpreload_")) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
__attribute__((__noreturn__))
|
||||
#endif
|
||||
@@ -107,6 +130,20 @@ write_done:
|
||||
* to debug. Another reason is that we must not cause external effects
|
||||
* such as destroying a PSA persistent key.)
|
||||
*/
|
||||
if (probably_running_under_valgrind()) {
|
||||
/* Valgrind overloads _exit(), and this makes it do weird things,
|
||||
* including an lseek() call to rewind the pointer on the file
|
||||
* description for the `.datax` file, causing the same test cases
|
||||
* to run again (or parse errors, depending on the exact amount
|
||||
* of rewinding).
|
||||
*
|
||||
* Valgrind doesn't overload execve() and friends. So instead of
|
||||
* _exit(), execute a shell command that returns the same status.
|
||||
*/
|
||||
char cmd[20];
|
||||
snprintf(cmd, sizeof(cmd), "exit %d", child_exit_code);
|
||||
execlp("sh", "sh", "-c", cmd, NULL);
|
||||
}
|
||||
_exit(child_exit_code);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user