https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/75267
>From 7fa7ea4786d3c8244aff575d3147d421c761e02a Mon Sep 17 00:00:00 2001 From: Vitaly Buka <vitalyb...@google.com> Date: Tue, 12 Dec 2023 17:01:54 -0800 Subject: [PATCH 1/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?= =?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 [skip ci] --- .../TestCases/Posix/fork_threaded.cpp | 86 +++++++++++++++++++ .../sanitizer_common/sanitizer_specific.h | 16 ++++ 2 files changed, 102 insertions(+) create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp new file mode 100644 index 00000000000000..72a2f78a5a3e77 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp @@ -0,0 +1,86 @@ +// RUN: %clangxx -O0 %s -o %t && %env_tool_opts=die_after_fork=0 %run %t + +// UNSUPPORTED: asan, lsan, hwasan + +// Forking in multithread environment is unsupported. However we already have +// some workarounds, and will add more, so this is the test. + +#include <assert.h> +#include <pthread.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "sanitizer_common/sanitizer_specific.h" + +static const size_t kBufferSize = 1 << 20; + +static void *background(void *arg) { return nullptr; } + +pthread_barrier_t bar; + +void CanDeadLock() { + // Don't bother with leaks, we try to trigger allocator or lsan deadlock. + __lsan::ScopedDisabler disable; + char *volatile p = new char[10]; + __lsan_do_recoverable_leak_check(); + delete[] p; +} + +// Prevent stack buffer cleanup by instrumentation. +#define NOSAN __attribute__((no_sanitize("address", "hwaddress", "memory"))) + +NOSAN static void *inparent(void *arg) { + fprintf(stderr, "inparent %d\n", gettid()); + + char t[kBufferSize]; + make_mem_bad(t, sizeof(t)); + + pthread_barrier_wait(&bar); + + for (;;) + CanDeadLock(); + + return 0; +} + +NOSAN static void *inchild(void *arg) { + char t[kBufferSize]; + check_mem_is_good(t, sizeof(t)); + CanDeadLock(); + return 0; +} + +int main(void) { + pid_t pid; + + pthread_barrier_init(&bar, nullptr, 2); + pthread_t thread_id; + while (pthread_create(&thread_id, 0, &inparent, 0) != 0) { + } + pthread_barrier_wait(&bar); + + pid = fork(); + switch (pid) { + case -1: + perror("fork"); + return -1; + case 0: + while (pthread_create(&thread_id, 0, &inchild, 0) != 0) { + } + break; + default: { + fprintf(stderr, "fork %d\n", pid); + int status; + while (waitpid(-1, &status, __WALL) != pid) { + } + assert(WIFEXITED(status) && WEXITSTATUS(status) == 0); + break; + } + } + + return 0; +} diff --git a/compiler-rt/test/sanitizer_common/sanitizer_specific.h b/compiler-rt/test/sanitizer_common/sanitizer_specific.h index 1a802020cfd668..963d91cb305f60 100644 --- a/compiler-rt/test/sanitizer_common/sanitizer_specific.h +++ b/compiler-rt/test/sanitizer_common/sanitizer_specific.h @@ -1,6 +1,12 @@ #ifndef __SANITIZER_COMMON_SANITIZER_SPECIFIC_H__ #define __SANITIZER_COMMON_SANITIZER_SPECIFIC_H__ +#include <sanitizer/lsan_interface.h> + +__attribute__((weak)) int __lsan_do_recoverable_leak_check() { return 0; } +__attribute__((weak)) void __lsan_disable(void) {} +__attribute__((weak)) void __lsan_enable(void) {} + #ifndef __has_feature # define __has_feature(x) 0 #endif @@ -10,6 +16,8 @@ static void check_mem_is_good(void *p, size_t s) { __msan_check_mem_is_initialized(p, s); } +static void make_mem_good(void *p, size_t s) { __msan_unpoison(p, s); } +static void make_mem_bad(void *p, size_t s) { __msan_poison(p, s); } #elif __has_feature(address_sanitizer) # include <sanitizer/asan_interface.h> # include <stdlib.h> @@ -17,8 +25,16 @@ static void check_mem_is_good(void *p, size_t s) { if (__asan_region_is_poisoned(p, s)) abort(); } +static void make_mem_good(void *p, size_t s) { + __asan_unpoison_memory_region(p, s); +} +static void make_mem_bad(void *p, size_t s) { + __asan_poison_memory_region(p, s); +} #else static void check_mem_is_good(void *p, size_t s) {} +static void make_mem_good(void *p, size_t s) {} +static void make_mem_bad(void *p, size_t s) {} #endif #endif // __SANITIZER_COMMON_SANITIZER_SPECIFIC_H__ \ No newline at end of file >From 6ed9198c136ead9c6726e5bfd83978e891522f5b Mon Sep 17 00:00:00 2001 From: Vitaly Buka <vitalyb...@google.com> Date: Tue, 12 Dec 2023 17:09:19 -0800 Subject: [PATCH 2/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?= =?UTF-8?q?anges=20introduced=20through=20rebase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 [skip ci] --- compiler-rt/test/sanitizer_common/sanitizer_specific.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/test/sanitizer_common/sanitizer_specific.h b/compiler-rt/test/sanitizer_common/sanitizer_specific.h index 963d91cb305f60..898899f00e3701 100644 --- a/compiler-rt/test/sanitizer_common/sanitizer_specific.h +++ b/compiler-rt/test/sanitizer_common/sanitizer_specific.h @@ -37,4 +37,4 @@ static void make_mem_good(void *p, size_t s) {} static void make_mem_bad(void *p, size_t s) {} #endif -#endif // __SANITIZER_COMMON_SANITIZER_SPECIFIC_H__ \ No newline at end of file +#endif // __SANITIZER_COMMON_SANITIZER_SPECIFIC_H__ >From 32bd6fc49d9eb1bd0beffce69ae30fad1e011453 Mon Sep 17 00:00:00 2001 From: Vitaly Buka <vitalyb...@google.com> Date: Tue, 12 Dec 2023 17:16:03 -0800 Subject: [PATCH 3/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?= =?UTF-8?q?anges=20introduced=20through=20rebase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 [skip ci] --- .../sanitizer_common/TestCases/Posix/fork_threaded.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp index 5f53aad4a989ba..e2d67341846c74 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp @@ -4,6 +4,10 @@ // Forking in multithread environment is unsupported. However we already have // some workarounds, and will add more, so this is the test. +// The test try to check two things: +// 1. Internal mutexes used by `inparent` thread do not deadlock `inchild` +// thread. +// 2. Stack poisoned by `inparent` is not poisoned in `inchild` thread. #include <assert.h> #include <pthread.h> @@ -22,7 +26,7 @@ pthread_barrier_t bar; // Without appropriate workarounds this code can cause the forked process to // start with locked internal mutexes. -void CanDeadLock() { +void ShouldNotDeadlock() { // Don't bother with leaks, we try to trigger allocator or lsan deadlock. __lsan::ScopedDisabler disable; char *volatile p = new char[10]; @@ -42,7 +46,7 @@ NOSAN static void *inparent(void *arg) { pthread_barrier_wait(&bar); for (;;) - CanDeadLock(); + ShouldNotDeadlock(); return 0; } @@ -50,7 +54,7 @@ NOSAN static void *inparent(void *arg) { NOSAN static void *inchild(void *arg) { char t[kBufferSize]; check_mem_is_good(t, sizeof(t)); - CanDeadLock(); + ShouldNotDeadlock(); return 0; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits