[compiler-rt] af4ae12 - [rtsan] Add fork/execve interceptors (#117198)

via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 4 16:38:41 PST 2024


Author: Chris Apple
Date: 2024-12-04T16:38:37-08:00
New Revision: af4ae12780099d3df0b89bccc80fd69b240f345e

URL: https://github.com/llvm/llvm-project/commit/af4ae12780099d3df0b89bccc80fd69b240f345e
DIFF: https://github.com/llvm/llvm-project/commit/af4ae12780099d3df0b89bccc80fd69b240f345e.diff

LOG: [rtsan] Add fork/execve interceptors (#117198)

Added: 
    compiler-rt/test/rtsan/fork_exec.cpp

Modified: 
    compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index 4262039e8e1fa6..4f7b534ee17a86 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -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
+// 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
@@ -956,6 +972,9 @@ void __rtsan::InitializeInterceptors() {
   INTERCEPT_FUNCTION(pipe);
   INTERCEPT_FUNCTION(mkfifo);
 
+  INTERCEPT_FUNCTION(fork);
+  INTERCEPT_FUNCTION(execve);
+
   INTERCEPT_FUNCTION(syscall);
 }
 

diff  --git a/compiler-rt/test/rtsan/fork_exec.cpp b/compiler-rt/test/rtsan/fork_exec.cpp
new file mode 100644
index 00000000000000..3b2d2e5ca2f5d2
--- /dev/null
+++ b/compiler-rt/test/rtsan/fork_exec.cpp
@@ -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 
diff icult to test in a gtest, because the process is
+//         wiped away with exec.
+
+#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


        


More information about the llvm-commits mailing list