xref: /llvm-project/compiler-rt/lib/gwp_asan/tests/enable_disable.cpp (revision dd1c4bd09dd7a48c744f58847862f2e2bd633477)
1596d0614SEvgenii Stepanov //===-- enable_disable.cpp --------------------------------------*- C++ -*-===//
2596d0614SEvgenii Stepanov //
3596d0614SEvgenii Stepanov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4596d0614SEvgenii Stepanov // See https://llvm.org/LICENSE.txt for license information.
5596d0614SEvgenii Stepanov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6596d0614SEvgenii Stepanov //
7596d0614SEvgenii Stepanov //===----------------------------------------------------------------------===//
8596d0614SEvgenii Stepanov 
9596d0614SEvgenii Stepanov #include "gwp_asan/tests/harness.h"
10596d0614SEvgenii Stepanov 
11596d0614SEvgenii Stepanov constexpr size_t Size = 100;
12596d0614SEvgenii Stepanov 
TEST_F(DefaultGuardedPoolAllocatorDeathTest,Fork)13*dd1c4bd0SMitch Phillips TEST_F(DefaultGuardedPoolAllocatorDeathTest, Fork) {
14596d0614SEvgenii Stepanov   void *P;
15596d0614SEvgenii Stepanov   pid_t Pid = fork();
16596d0614SEvgenii Stepanov   EXPECT_GE(Pid, 0);
17596d0614SEvgenii Stepanov   if (Pid == 0) {
18596d0614SEvgenii Stepanov     P = GPA.allocate(Size);
19596d0614SEvgenii Stepanov     EXPECT_NE(P, nullptr);
20596d0614SEvgenii Stepanov     memset(P, 0x42, Size);
21596d0614SEvgenii Stepanov     GPA.deallocate(P);
22596d0614SEvgenii Stepanov     _exit(0);
23596d0614SEvgenii Stepanov   }
24596d0614SEvgenii Stepanov   waitpid(Pid, nullptr, 0);
25596d0614SEvgenii Stepanov   P = GPA.allocate(Size);
26596d0614SEvgenii Stepanov   EXPECT_NE(P, nullptr);
27596d0614SEvgenii Stepanov   memset(P, 0x42, Size);
28596d0614SEvgenii Stepanov   GPA.deallocate(P);
29596d0614SEvgenii Stepanov 
30596d0614SEvgenii Stepanov   // fork should stall if the allocator has been disabled.
31596d0614SEvgenii Stepanov   EXPECT_DEATH(
32596d0614SEvgenii Stepanov       {
33596d0614SEvgenii Stepanov         GPA.disable();
34596d0614SEvgenii Stepanov         alarm(1);
35596d0614SEvgenii Stepanov         Pid = fork();
36596d0614SEvgenii Stepanov         EXPECT_GE(Pid, 0);
37596d0614SEvgenii Stepanov       },
38596d0614SEvgenii Stepanov       "");
39596d0614SEvgenii Stepanov }
40596d0614SEvgenii Stepanov 
41596d0614SEvgenii Stepanov namespace {
42596d0614SEvgenii Stepanov pthread_mutex_t Mutex;
43596d0614SEvgenii Stepanov pthread_cond_t Conditional = PTHREAD_COND_INITIALIZER;
44596d0614SEvgenii Stepanov bool ThreadReady = false;
45596d0614SEvgenii Stepanov 
enableMalloc(void * arg)46596d0614SEvgenii Stepanov void *enableMalloc(void *arg) {
47596d0614SEvgenii Stepanov   auto &GPA = *reinterpret_cast<gwp_asan::GuardedPoolAllocator *>(arg);
48596d0614SEvgenii Stepanov 
49596d0614SEvgenii Stepanov   // Signal the main thread we are ready.
50596d0614SEvgenii Stepanov   pthread_mutex_lock(&Mutex);
51596d0614SEvgenii Stepanov   ThreadReady = true;
52596d0614SEvgenii Stepanov   pthread_cond_signal(&Conditional);
53596d0614SEvgenii Stepanov   pthread_mutex_unlock(&Mutex);
54596d0614SEvgenii Stepanov 
55596d0614SEvgenii Stepanov   // Wait for the malloc_disable & fork, then enable the allocator again.
56596d0614SEvgenii Stepanov   sleep(1);
57596d0614SEvgenii Stepanov   GPA.enable();
58596d0614SEvgenii Stepanov 
59596d0614SEvgenii Stepanov   return nullptr;
60596d0614SEvgenii Stepanov }
61596d0614SEvgenii Stepanov 
TEST_F(DefaultGuardedPoolAllocator,DisableForkEnable)62596d0614SEvgenii Stepanov TEST_F(DefaultGuardedPoolAllocator, DisableForkEnable) {
63596d0614SEvgenii Stepanov   pthread_t ThreadId;
64596d0614SEvgenii Stepanov   EXPECT_EQ(pthread_create(&ThreadId, nullptr, &enableMalloc, &GPA), 0);
65596d0614SEvgenii Stepanov 
66596d0614SEvgenii Stepanov   // Do not lock the allocator right away, the other thread may need it to start
67596d0614SEvgenii Stepanov   // up.
68596d0614SEvgenii Stepanov   pthread_mutex_lock(&Mutex);
69596d0614SEvgenii Stepanov   while (!ThreadReady)
70596d0614SEvgenii Stepanov     pthread_cond_wait(&Conditional, &Mutex);
71596d0614SEvgenii Stepanov   pthread_mutex_unlock(&Mutex);
72596d0614SEvgenii Stepanov 
73596d0614SEvgenii Stepanov   // Disable the allocator and fork. fork should succeed after malloc_enable.
74596d0614SEvgenii Stepanov   GPA.disable();
75596d0614SEvgenii Stepanov   pid_t Pid = fork();
76596d0614SEvgenii Stepanov   EXPECT_GE(Pid, 0);
77596d0614SEvgenii Stepanov   if (Pid == 0) {
78596d0614SEvgenii Stepanov     void *P = GPA.allocate(Size);
79596d0614SEvgenii Stepanov     EXPECT_NE(P, nullptr);
80596d0614SEvgenii Stepanov     GPA.deallocate(P);
81596d0614SEvgenii Stepanov     _exit(0);
82596d0614SEvgenii Stepanov   }
83596d0614SEvgenii Stepanov   waitpid(Pid, nullptr, 0);
84596d0614SEvgenii Stepanov   EXPECT_EQ(pthread_join(ThreadId, 0), 0);
85596d0614SEvgenii Stepanov }
86596d0614SEvgenii Stepanov } // namespace
87