diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -2422,6 +2422,50 @@ #define INIT_GLOB64 #endif // SANITIZER_INTERCEPT_GLOB64 +#if SANITIZER_INTERCEPT_POSIX_SPAWN + +template +static int PosixSpawnImpl(void *ctx, RealSpawnPtr *real_posix_spawn, pid_t *pid, + const char *file_or_path, const void *file_actions, + const void *attrp, char *const argv[], + char *const envp[]) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, file_or_path, + internal_strlen(file_or_path) + 1); + for (const char *const *s = argv; *s; ++s) + COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1); + for (const char *const *s = envp; *s; ++s) + COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1); + int res = + real_posix_spawn(pid, file_or_path, file_actions, attrp, argv, envp); + if (res == 0) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pid, sizeof(*pid)); + return res; +} +INTERCEPTOR(int, posix_spawn, pid_t *pid, const char *path, + const void *file_actions, const void *attrp, char *const argv[], + char *const envp[]) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, posix_spawn, pid, path, file_actions, attrp, + argv, envp); + return PosixSpawnImpl(ctx, REAL(posix_spawn), pid, path, file_actions, attrp, + argv, envp); +} +INTERCEPTOR(int, posix_spawnp, pid_t *pid, const char *file, + const void *file_actions, const void *attrp, char *const argv[], + char *const envp[]) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, posix_spawnp, pid, file, file_actions, attrp, + argv, envp); + return PosixSpawnImpl(ctx, REAL(posix_spawnp), pid, file, file_actions, attrp, + argv, envp); +} +# define INIT_POSIX_SPAWN \ + COMMON_INTERCEPT_FUNCTION(posix_spawn); \ + COMMON_INTERCEPT_FUNCTION(posix_spawnp); +#else // SANITIZER_INTERCEPT_POSIX_SPAWN +# define INIT_POSIX_SPAWN +#endif // SANITIZER_INTERCEPT_POSIX_SPAWN + #if SANITIZER_INTERCEPT_WAIT // According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version // suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for @@ -10229,6 +10273,7 @@ INIT_TIME; INIT_GLOB; INIT_GLOB64; + INIT_POSIX_SPAWN; INIT_WAIT; INIT_WAIT4; INIT_INET; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -235,6 +235,7 @@ #define SANITIZER_INTERCEPT_TIME SI_POSIX #define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS) #define SANITIZER_INTERCEPT_GLOB64 SI_GLIBC +#define SANITIZER_INTERCEPT_POSIX_SPAWN SI_POSIX #define SANITIZER_INTERCEPT_WAIT SI_POSIX #define SANITIZER_INTERCEPT_INET SI_POSIX #define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_POSIX diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/posix_spawn.c b/compiler-rt/test/sanitizer_common/TestCases/Posix/posix_spawn.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/posix_spawn.c @@ -0,0 +1,40 @@ +// RUN: %clang %s -o %t && %run %t 2>&1 | FileCheck %s + +#include +#include +#include +#include + +int main(int argc, char **argv) { + if (argc > 1) { + // CHECK: SPAWNED + // CHECK: SPAWNED + printf("SPAWNED\n"); + return 0; + } + + int s; + + posix_spawnattr_t attr; + s = posix_spawnattr_init(&attr); + assert(!s); + + posix_spawn_file_actions_t file_actions; + s = posix_spawn_file_actions_init(&file_actions); + assert(!s); + + char *const args[] = {argv[0], "2", NULL}; + char *const env[] = {"A=B", NULL}; + + pid_t pid; + s = posix_spawn(&pid, argv[0], &file_actions, &attr, args, env); + assert(!s); + + waitpid(pid, &s, WUNTRACED | WCONTINUED); + + s = posix_spawnp(&pid, argv[0], &file_actions, &attr, args, env); + assert(!s); + + waitpid(pid, &s, WUNTRACED | WCONTINUED); + return 0; +}