diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp index 9d1a689a5a070..53d7d1b87ba7a 100644 --- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp @@ -1411,6 +1411,31 @@ INTERCEPTOR(int, execve, const char *filename, char *const argv[], return REAL(execve)(filename, argv, envp); } +#if SANITIZER_GLIBC +INTERCEPTOR(int, clone, int (*f)(void *), void *stack, int flags, void *arg, + ...) { + __rtsan_notify_intercepted_call("clone"); + + if ((flags & CLONE_PIDFD) || (flags & CLONE_SETTLS) || + (flags & CLONE_PARENT_SETTID) || (flags & CLONE_CHILD_SETTID) || + (flags & CLONE_CHILD_CLEARTID)) { + va_list args; + va_start(args, arg); + pid_t *parent = va_arg(args, pid_t *); + void *tls = va_arg(args, void *); + pid_t *child = va_arg(args, pid_t *); + va_end(args); + + return REAL(clone)(f, stack, flags, arg, parent, tls, child); + } + + return REAL(clone)(f, stack, flags, arg); +} +#define RTSAN_MAYBE_INTERCEPT_CLONE INTERCEPT_FUNCTION(clone) +#else +#define RTSAN_MAYBE_INTERCEPT_CLONE +#endif + #if SANITIZER_INTERCEPT_PROCESS_VM_READV INTERCEPTOR(ssize_t, process_vm_readv, pid_t pid, const struct iovec *local_iov, unsigned long liovcnt, const struct iovec *remote_iov, @@ -1650,6 +1675,7 @@ void __rtsan::InitializeInterceptors() { INTERCEPT_FUNCTION(fork); INTERCEPT_FUNCTION(execve); + RTSAN_MAYBE_INTERCEPT_CLONE; RTSAN_MAYBE_INTERCEPT_PROCESS_VM_READV; RTSAN_MAYBE_INTERCEPT_PROCESS_VM_WRITEV; diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp index f12df9ea90855..4f94dd4bde5bd 100644 --- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp @@ -1273,6 +1273,35 @@ TEST_F(PthreadRwlockTest, PthreadRwlockWrlockSurvivesWhenNonRealtime) { ExpectNonRealtimeSurvival(Func); } +#if SANITIZER_GLIBC +TEST(TestRtsanInterceptors, CloneDiesWhenRealtime) { + std::vector buf; + buf.resize(1024 * 1024); + auto Call = [](void *a) { return 0; }; + auto Func = [&buf, &Call]() { + clone(Call, buf.data() + buf.size(), 0, nullptr); + }; + + ExpectRealtimeDeath(Func, "clone"); + ExpectNonRealtimeSurvival(Func); +} + +TEST(TestRtsanInterceptors, CloneWithTldDiesWhenRealtime) { + std::vector buf; + pid_t pidfd; + void *tls = ::operator new(4096, std::align_val_t(16)); + buf.resize(1024 * 1024); + auto Call = [](void *a) { return 0; }; + auto Func = [&buf, &Call, &pidfd, &tls]() { + clone(Call, buf.data() + buf.size(), CLONE_PIDFD | CLONE_SETTLS, &pidfd, + tls, nullptr); + }; + + ExpectRealtimeDeath(Func, "clone"); + ExpectNonRealtimeSurvival(Func); +} +#endif + /* Sockets */