• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <gtest/gtest.h>
30 #include <stdio.h>
31 #include <sys/file.h>
32 #include <string>
33 
34 #if defined(__BIONIC__)
35 
36 #include "android-base/file.h"
37 #include "gwp_asan/options.h"
38 #include "platform/bionic/malloc.h"
39 #include "sys/system_properties.h"
40 #include "utils.h"
41 
42 // basename is a mess, use gnu basename explicitly to avoid the need for string
43 // mutation.
44 extern "C" const char* __gnu_basename(const char* path);
45 
46 // GWP-ASan tests can run much slower, especially when combined with HWASan.
47 // Triple the deadline to avoid flakes (b/238585984).
GetInitialArgs(const char *** args,size_t * num_args)48 extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
49   static const char* initial_args[] = {"--deadline_threshold_ms=270000"};
50   *args = initial_args;
51   *num_args = 1;
52   return true;
53 }
54 
55 // This file implements "torture testing" under GWP-ASan, where we sample every
56 // single allocation. The upper limit for the number of GWP-ASan allocations in
57 // the torture mode is is generally 40,000, so that svelte devices don't
58 // explode, as this uses ~163MiB RAM (4KiB per live allocation).
TEST(gwp_asan_integration,malloc_tests_under_torture)59 TEST(gwp_asan_integration, malloc_tests_under_torture) {
60   RunGwpAsanTest("malloc.*:-malloc.mallinfo*");
61 }
62 
63 class SyspropRestorer {
64  private:
65   std::vector<std::pair<std::string, std::string>> props_to_restore_;
66   // System properties are global for a device, so the tests that mutate the
67   // GWP-ASan system properties must be run mutually exclusive. Because
68   // bionic-unit-tests is run in an isolated gtest fashion (each test is run in
69   // its own process), we have to use flocks to synchronise between tests.
70   int flock_fd_;
71 
72  public:
SyspropRestorer()73   SyspropRestorer() {
74     std::string path = testing::internal::GetArgvs()[0];
75     flock_fd_ = open(path.c_str(), O_RDONLY);
76     EXPECT_NE(flock_fd_, -1) << "failed to open self for a flock";
77     EXPECT_NE(flock(flock_fd_, LOCK_EX), -1) << "failed to flock myself";
78 
79     const char* basename = __gnu_basename(path.c_str());
80     std::vector<std::string> props = {
81         std::string("libc.debug.gwp_asan.sample_rate.") + basename,
82         std::string("libc.debug.gwp_asan.process_sampling.") + basename,
83         std::string("libc.debug.gwp_asan.max_allocs.") + basename,
84         "libc.debug.gwp_asan.sample_rate.system_default",
85         "libc.debug.gwp_asan.sample_rate.app_default",
86         "libc.debug.gwp_asan.process_sampling.system_default",
87         "libc.debug.gwp_asan.process_sampling.app_default",
88         "libc.debug.gwp_asan.max_allocs.system_default",
89         "libc.debug.gwp_asan.max_allocs.app_default",
90     };
91 
92     size_t base_props_size = props.size();
93     for (size_t i = 0; i < base_props_size; ++i) {
94       props.push_back("persist." + props[i]);
95     }
96 
97     std::string reset_log;
98 
99     for (const std::string& prop : props) {
100       std::string value = GetSysprop(prop);
101       props_to_restore_.emplace_back(prop, value);
102       if (!value.empty()) {
103         __system_property_set(prop.c_str(), "");
104       }
105     }
106   }
107 
~SyspropRestorer()108   ~SyspropRestorer() {
109     for (const auto& kv : props_to_restore_) {
110       if (kv.second != GetSysprop(kv.first)) {
111         __system_property_set(kv.first.c_str(), kv.second.c_str());
112       }
113     }
114     close(flock_fd_);
115   }
116 
GetSysprop(const std::string & name)117   static std::string GetSysprop(const std::string& name) {
118     std::string value;
119     const prop_info* pi = __system_property_find(name.c_str());
120     if (pi == nullptr) return value;
121     __system_property_read_callback(
122         pi,
123         [](void* cookie, const char* /* name */, const char* value, uint32_t /* serial */) {
124           std::string* v = static_cast<std::string*>(cookie);
125           *v = value;
126         },
127         &value);
128     return value;
129   }
130 };
131 
TEST(gwp_asan_integration,DISABLED_assert_gwp_asan_enabled)132 TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_enabled) {
133   std::string maps;
134   EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
135   EXPECT_TRUE(maps.find("GWP-ASan") != std::string::npos) << maps;
136 
137   volatile int* x = new int;
138   delete x;
139   EXPECT_DEATH({ *x = 7; }, "");
140 }
141 
TEST(gwp_asan_integration,DISABLED_assert_gwp_asan_disabled)142 TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_disabled) {
143   std::string maps;
144   EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
145   EXPECT_TRUE(maps.find("GWP-ASan") == std::string::npos);
146 }
147 
TEST(gwp_asan_integration,sysprops_program_specific)148 TEST(gwp_asan_integration, sysprops_program_specific) {
149   SyspropRestorer restorer;
150 
151   std::string path = testing::internal::GetArgvs()[0];
152   const char* basename = __gnu_basename(path.c_str());
153   __system_property_set((std::string("libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
154   __system_property_set((std::string("libc.debug.gwp_asan.process_sampling.") + basename).c_str(),
155                         "1");
156   __system_property_set((std::string("libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
157                         "40000");
158 
159   RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
160 }
161 
TEST(gwp_asan_integration,sysprops_persist_program_specific)162 TEST(gwp_asan_integration, sysprops_persist_program_specific) {
163   SyspropRestorer restorer;
164 
165   std::string path = testing::internal::GetArgvs()[0];
166   const char* basename = __gnu_basename(path.c_str());
167   __system_property_set(
168       (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
169   __system_property_set(
170       (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
171   __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
172                         "40000");
173 
174   RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
175 }
176 
TEST(gwp_asan_integration,sysprops_system)177 TEST(gwp_asan_integration, sysprops_system) {
178   SyspropRestorer restorer;
179 
180   __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1");
181   __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1");
182   __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "40000");
183 
184   RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
185 }
186 
TEST(gwp_asan_integration,sysprops_persist_system)187 TEST(gwp_asan_integration, sysprops_persist_system) {
188   SyspropRestorer restorer;
189 
190   __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "1");
191   __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "1");
192   __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "40000");
193 
194   RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
195 }
196 
TEST(gwp_asan_integration,sysprops_non_persist_overrides_persist)197 TEST(gwp_asan_integration, sysprops_non_persist_overrides_persist) {
198   SyspropRestorer restorer;
199 
200   __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1");
201   __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1");
202   __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "40000");
203 
204   __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "0");
205   __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "0");
206   __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "0");
207 
208   RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
209 }
210 
TEST(gwp_asan_integration,sysprops_program_specific_overrides_default)211 TEST(gwp_asan_integration, sysprops_program_specific_overrides_default) {
212   SyspropRestorer restorer;
213 
214   std::string path = testing::internal::GetArgvs()[0];
215   const char* basename = __gnu_basename(path.c_str());
216   __system_property_set(
217       (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
218   __system_property_set(
219       (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
220   __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
221                         "40000");
222 
223   __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
224   __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
225   __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
226 
227   RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
228 }
229 
TEST(gwp_asan_integration,sysprops_can_disable)230 TEST(gwp_asan_integration, sysprops_can_disable) {
231   SyspropRestorer restorer;
232 
233   __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
234   __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
235   __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
236 
237   RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_disabled");
238 }
239 
TEST(gwp_asan_integration,env_overrides_sysprop)240 TEST(gwp_asan_integration, env_overrides_sysprop) {
241   SyspropRestorer restorer;
242 
243   __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
244   __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
245   __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
246 
247   RunGwpAsanTest("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
248 }
249 
250 #endif  // defined(__BIONIC__)
251