blob: 5f5e3dd178cec5a4337a6e79b9ca4998370b32d7 [file] [log] [blame]
Mitch Phillipse6997d52020-11-30 15:04:14 -08001/*
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>
Mitch Phillips9634c362022-06-23 11:07:00 -070031#include <sys/file.h>
Mitch Phillipse6997d52020-11-30 15:04:14 -080032#include <string>
33
34#if defined(__BIONIC__)
35
Mitch Phillips9634c362022-06-23 11:07:00 -070036#include "android-base/file.h"
Mitch Phillipse6997d52020-11-30 15:04:14 -080037#include "gwp_asan/options.h"
38#include "platform/bionic/malloc.h"
Mitch Phillips9634c362022-06-23 11:07:00 -070039#include "sys/system_properties.h"
Mitch Phillipse6997d52020-11-30 15:04:14 -080040#include "utils.h"
41
Mitch Phillips9634c362022-06-23 11:07:00 -070042// basename is a mess, use gnu basename explicitly to avoid the need for string
43// mutation.
44extern "C" const char* __gnu_basename(const char* path);
Mitch Phillipse6997d52020-11-30 15:04:14 -080045
Mitch Phillips1f3c8d62022-07-11 09:31:41 -070046// GWP-ASan tests can run much slower, especially when combined with HWASan.
47// Triple the deadline to avoid flakes (b/238585984).
48extern "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
Mitch Phillipse6997d52020-11-30 15:04:14 -080055// 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).
59TEST(gwp_asan_integration, malloc_tests_under_torture) {
60 RunGwpAsanTest("malloc.*:-malloc.mallinfo*");
61}
62
Mitch Phillips9634c362022-06-23 11:07:00 -070063class 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:
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
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
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
132TEST(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
142TEST(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
148TEST(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
162TEST(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
177TEST(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
187TEST(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
197TEST(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
211TEST(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
230TEST(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
240TEST(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
Mitch Phillipse6997d52020-11-30 15:04:14 -0800250#endif // defined(__BIONIC__)