Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,22 @@ INTERCEPTOR(int, mkfifo, const char *pathname, mode_t mode) {
return REAL(mkfifo)(pathname, mode);
}

INTERCEPTOR(pid_t, fork, void) {
__rtsan_notify_intercepted_call("fork");
return REAL(fork)();
}

INTERCEPTOR(int, execve, const char *filename, char *const argv[],
char *const envp[]) {
__rtsan_notify_intercepted_call("execve");
return REAL(execve)(filename, argv, envp);
}

// TODO: the `wait` family of functions is an oddity. In testing, if you
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drawing folks attention here

// intercept them, Darwin seemingly ignores them, and linux never returns from
// the test. Revisit this in the future, but hopefully intercepting fork/exec is
// enough to dissuade usage of wait by proxy.

#if SANITIZER_APPLE
#define INT_TYPE_SYSCALL int
#else
Expand Down Expand Up @@ -956,6 +972,9 @@ void __rtsan::InitializeInterceptors() {
INTERCEPT_FUNCTION(pipe);
INTERCEPT_FUNCTION(mkfifo);

INTERCEPT_FUNCTION(fork);
INTERCEPT_FUNCTION(execve);

INTERCEPT_FUNCTION(syscall);
}

Expand Down
59 changes: 59 additions & 0 deletions compiler-rt/test/rtsan/fork_exec.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// RUN: %clangxx -fsanitize=realtime -DIS_NONBLOCKING=1 %s -o %t
// RUN: %env_rtsan_opts="halt_on_error=true" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-HALT
// RUN: %env_rtsan_opts="halt_on_error=false" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOHALT

// RUN: %clangxx -fsanitize=realtime -DIS_NONBLOCKING=0 %s -o %t
// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-OK
// RUN: %env_rtsan_opts="halt_on_error=false" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-OK

// UNSUPPORTED: ios

// Intent: Ensure fork/exec dies when realtime and survives otherwise
// This behavior is difficult to test in a gtest, because the process is
// wiped away with exec.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here


#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#if IS_NONBLOCKING
# define MAYBE_NONBLOCKING [[clang::nonblocking]]
#else
# define MAYBE_NONBLOCKING
#endif

int main() MAYBE_NONBLOCKING {
const pid_t pid = fork();

if (pid == 0) {
char *args[] = {"/bin/ls", nullptr};
execve(args[0], args, nullptr);
perror("execve failed");
return 1;
} else if (pid > 0) {
int status;
waitpid(pid, &status, 0);
usleep(1);
} else {
perror("fork failed");
return 1;
}

printf("fork/exec succeeded\n");
return 0;
}

// CHECK-NOHALT: Intercepted call to {{.*}} `fork` {{.*}}
// CHECK-NOHALT: Intercepted call to {{.*}} `execve` {{.*}}

// usleep checks that rtsan is still enabled in the parent process
// See note in our interceptors file for why we don't look for `wait`
// CHECK-NOHALT: Intercepted call to {{.*}} `usleep` {{.*}}

// CHECK-NOHALT: fork/exec succeeded

// CHECK-HALT: ==ERROR: RealtimeSanitizer: unsafe-library-call
// CHECK-HALT-NEXT: Intercepted call to {{.*}} `fork` {{.*}}

// CHECK-OK: fork/exec succeeded
Loading