• 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 "android-base/test_utils.h"
38 #include "gwp_asan/options.h"
39 #include "platform/bionic/malloc.h"
40 #include "sys/system_properties.h"
41 #include "utils.h"
42 
43 // basename is a mess, use gnu basename explicitly to avoid the need for string
44 // mutation.
45 extern "C" const char* __gnu_basename(const char* path);
46 
47 // GWP-ASan tests can run much slower, especially when combined with HWASan.
48 // Triple the deadline to avoid flakes (b/238585984).
GetInitialArgs(const char *** args,size_t * num_args)49 extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
50   static const char* initial_args[] = {"--deadline_threshold_ms=270000"};
51   *args = initial_args;
52   *num_args = 1;
53   return true;
54 }
55 
56 // This file implements "torture testing" under GWP-ASan, where we sample every
57 // single allocation. The upper limit for the number of GWP-ASan allocations in
58 // the torture mode is is generally 40,000, so that svelte devices don't
59 // explode, as this uses ~163MiB RAM (4KiB per live allocation).
TEST(gwp_asan_integration,malloc_tests_under_torture)60 TEST(gwp_asan_integration, malloc_tests_under_torture) {
61   // Do not override HWASan with GWP ASan.
62   SKIP_WITH_HWASAN;
63 
64   RunGwpAsanTest("malloc.*:-malloc.mallinfo*");
65 }
66 
67 class SyspropRestorer {
68  private:
69   std::vector<std::pair<std::string, std::string>> props_to_restore_;
70   // System properties are global for a device, so the tests that mutate the
71   // GWP-ASan system properties must be run mutually exclusive. Because
72   // bionic-unit-tests is run in an isolated gtest fashion (each test is run in
73   // its own process), we have to use flocks to synchronise between tests.
74   int flock_fd_;
75 
76  public:
SyspropRestorer()77   SyspropRestorer() {
78     std::string path = testing::internal::GetArgvs()[0];
79     flock_fd_ = open(path.c_str(), O_RDONLY);
80     EXPECT_NE(flock_fd_, -1) << "failed to open self for a flock";
81     EXPECT_NE(flock(flock_fd_, LOCK_EX), -1) << "failed to flock myself";
82 
83     const char* basename = __gnu_basename(path.c_str());
84     std::vector<std::string> props = {
85         std::string("libc.debug.gwp_asan.sample_rate.") + basename,
86         std::string("libc.debug.gwp_asan.process_sampling.") + basename,
87         std::string("libc.debug.gwp_asan.max_allocs.") + basename,
88         "libc.debug.gwp_asan.sample_rate.system_default",
89         "libc.debug.gwp_asan.sample_rate.app_default",
90         "libc.debug.gwp_asan.process_sampling.system_default",
91         "libc.debug.gwp_asan.process_sampling.app_default",
92         "libc.debug.gwp_asan.max_allocs.system_default",
93         "libc.debug.gwp_asan.max_allocs.app_default",
94     };
95 
96     size_t base_props_size = props.size();
97     for (size_t i = 0; i < base_props_size; ++i) {
98       props.push_back("persist." + props[i]);
99     }
100 
101     std::string reset_log;
102 
103     for (const std::string& prop : props) {
104       std::string value = GetSysprop(prop);
105       props_to_restore_.emplace_back(prop, value);
106       if (!value.empty()) {
107         __system_property_set(prop.c_str(), "");
108       }
109     }
110   }
111 
~SyspropRestorer()112   ~SyspropRestorer() {
113     for (const auto& kv : props_to_restore_) {
114       if (kv.second != GetSysprop(kv.first)) {
115         __system_property_set(kv.first.c_str(), kv.second.c_str());
116       }
117     }
118     close(flock_fd_);
119   }
120 
GetSysprop(const std::string & name)121   static std::string GetSysprop(const std::string& name) {
122     std::string value;
123     const prop_info* pi = __system_property_find(name.c_str());
124     if (pi == nullptr) return value;
125     __system_property_read_callback(
126         pi,
127         [](void* cookie, const char* /* name */, const char* value, uint32_t /* serial */) {
128           std::string* v = static_cast<std::string*>(cookie);
129           *v = value;
130         },
131         &value);
132     return value;
133   }
134 };
135 
TEST(gwp_asan_integration,DISABLED_assert_gwp_asan_enabled)136 TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_enabled) {
137   std::string maps;
138   EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
139   EXPECT_TRUE(maps.find("GWP-ASan") != std::string::npos) << maps;
140 
141   volatile int* x = new int;
142   delete x;
143   EXPECT_DEATH({ *x = 7; }, "");
144 }
145 
146 // A weaker version of the above tests, only checking that GWP-ASan is enabled
147 // for any pointer, not *our* pointer. This allows us to test the system_default
148 // sysprops without potentially OOM-ing other random processes:
149 // b/273904016#comment5
TEST(gwp_asan_integration,DISABLED_assert_gwp_asan_enabled_weaker)150 TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_enabled_weaker) {
151   std::string maps;
152   EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
153   EXPECT_TRUE(maps.find("GWP-ASan") != std::string::npos) << maps;
154 }
155 
TEST(gwp_asan_integration,DISABLED_assert_gwp_asan_disabled)156 TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_disabled) {
157   std::string maps;
158   EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
159   EXPECT_TRUE(maps.find("GWP-ASan") == std::string::npos);
160 }
161 
TEST(gwp_asan_integration,sysprops_program_specific)162 TEST(gwp_asan_integration, sysprops_program_specific) {
163   // Do not override HWASan with GWP ASan.
164   SKIP_WITH_HWASAN;
165 
166   SyspropRestorer restorer;
167 
168   std::string path = testing::internal::GetArgvs()[0];
169   const char* basename = __gnu_basename(path.c_str());
170   __system_property_set((std::string("libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
171   __system_property_set((std::string("libc.debug.gwp_asan.process_sampling.") + basename).c_str(),
172                         "1");
173   __system_property_set((std::string("libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
174                         "40000");
175 
176   RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
177 }
178 
TEST(gwp_asan_integration,sysprops_persist_program_specific)179 TEST(gwp_asan_integration, sysprops_persist_program_specific) {
180   // Do not override HWASan with GWP ASan.
181   SKIP_WITH_HWASAN;
182 
183   SyspropRestorer restorer;
184 
185   std::string path = testing::internal::GetArgvs()[0];
186   const char* basename = __gnu_basename(path.c_str());
187   __system_property_set(
188       (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
189   __system_property_set(
190       (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
191   __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
192                         "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   // Do not override HWASan with GWP ASan.
199   SKIP_WITH_HWASAN;
200 
201   SyspropRestorer restorer;
202 
203   __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1");
204   __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1");
205   // Note, any processes launched elsewhere on the system right now will have
206   // GWP-ASan enabled. Make sure that we only use a single slot, otherwise we
207   // could end up causing said badly-timed processes to use up to 163MiB extra
208   // penalty that 40,000 allocs would cause. See b/273904016#comment5 for more
209   // context.
210   __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "1");
211 
212   __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "0");
213   __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "0");
214   __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "0");
215 
216   RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled_weaker");
217 }
218 
TEST(gwp_asan_integration,sysprops_program_specific_overrides_default)219 TEST(gwp_asan_integration, sysprops_program_specific_overrides_default) {
220   // Do not override HWASan with GWP ASan.
221   SKIP_WITH_HWASAN;
222 
223   SyspropRestorer restorer;
224 
225   std::string path = testing::internal::GetArgvs()[0];
226   const char* basename = __gnu_basename(path.c_str());
227   __system_property_set(
228       (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
229   __system_property_set(
230       (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
231   __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
232                         "40000");
233 
234   __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
235   __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
236   __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
237 
238   RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
239 }
240 
TEST(gwp_asan_integration,sysprops_can_disable)241 TEST(gwp_asan_integration, sysprops_can_disable) {
242   // Do not override HWASan with GWP ASan.
243   SKIP_WITH_HWASAN;
244 
245   SyspropRestorer restorer;
246 
247   __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
248   __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
249   __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
250 
251   RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_disabled");
252 }
253 
TEST(gwp_asan_integration,env_overrides_sysprop)254 TEST(gwp_asan_integration, env_overrides_sysprop) {
255   // Do not override HWASan with GWP ASan.
256   SKIP_WITH_HWASAN;
257 
258   SyspropRestorer restorer;
259 
260   __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
261   __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
262   __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
263 
264   RunGwpAsanTest("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
265 }
266 
267 #endif  // defined(__BIONIC__)
268