blob: 38661c74ff6f04933a01baf9f47e715fea4bd97b [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"
Christopher Ferris8ab38e22023-02-06 18:57:18 -080037#include "android-base/test_utils.h"
Mitch Phillipse6997d52020-11-30 15:04:14 -080038#include "gwp_asan/options.h"
39#include "platform/bionic/malloc.h"
Mitch Phillips9634c362022-06-23 11:07:00 -070040#include "sys/system_properties.h"
Mitch Phillipse6997d52020-11-30 15:04:14 -080041#include "utils.h"
42
Mitch Phillips9634c362022-06-23 11:07:00 -070043// basename is a mess, use gnu basename explicitly to avoid the need for string
44// mutation.
45extern "C" const char* __gnu_basename(const char* path);
Mitch Phillipse6997d52020-11-30 15:04:14 -080046
Mitch Phillips1f3c8d62022-07-11 09:31:41 -070047// GWP-ASan tests can run much slower, especially when combined with HWASan.
48// Triple the deadline to avoid flakes (b/238585984).
49extern "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
Mitch Phillipse6997d52020-11-30 15:04:14 -080056// 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).
60TEST(gwp_asan_integration, malloc_tests_under_torture) {
Christopher Ferris8ab38e22023-02-06 18:57:18 -080061 if (running_with_hwasan()) {
62 // Skip the malloc.zeroed tests since they fail in this particular config.
63 // TODO(b/267386540): Need to fix this problem.
64 RunGwpAsanTest("malloc.*:-malloc.mallinfo*:malloc.zeroed*");
65 } else {
66 RunGwpAsanTest("malloc.*:-malloc.mallinfo*");
67 }
Mitch Phillipse6997d52020-11-30 15:04:14 -080068}
69
Mitch Phillips9634c362022-06-23 11:07:00 -070070class SyspropRestorer {
71 private:
72 std::vector<std::pair<std::string, std::string>> props_to_restore_;
73 // System properties are global for a device, so the tests that mutate the
74 // GWP-ASan system properties must be run mutually exclusive. Because
75 // bionic-unit-tests is run in an isolated gtest fashion (each test is run in
76 // its own process), we have to use flocks to synchronise between tests.
77 int flock_fd_;
78
79 public:
80 SyspropRestorer() {
81 std::string path = testing::internal::GetArgvs()[0];
82 flock_fd_ = open(path.c_str(), O_RDONLY);
83 EXPECT_NE(flock_fd_, -1) << "failed to open self for a flock";
84 EXPECT_NE(flock(flock_fd_, LOCK_EX), -1) << "failed to flock myself";
85
86 const char* basename = __gnu_basename(path.c_str());
87 std::vector<std::string> props = {
88 std::string("libc.debug.gwp_asan.sample_rate.") + basename,
89 std::string("libc.debug.gwp_asan.process_sampling.") + basename,
90 std::string("libc.debug.gwp_asan.max_allocs.") + basename,
91 "libc.debug.gwp_asan.sample_rate.system_default",
92 "libc.debug.gwp_asan.sample_rate.app_default",
93 "libc.debug.gwp_asan.process_sampling.system_default",
94 "libc.debug.gwp_asan.process_sampling.app_default",
95 "libc.debug.gwp_asan.max_allocs.system_default",
96 "libc.debug.gwp_asan.max_allocs.app_default",
97 };
98
99 size_t base_props_size = props.size();
100 for (size_t i = 0; i < base_props_size; ++i) {
101 props.push_back("persist." + props[i]);
102 }
103
104 std::string reset_log;
105
106 for (const std::string& prop : props) {
107 std::string value = GetSysprop(prop);
108 props_to_restore_.emplace_back(prop, value);
109 if (!value.empty()) {
110 __system_property_set(prop.c_str(), "");
111 }
112 }
113 }
114
115 ~SyspropRestorer() {
116 for (const auto& kv : props_to_restore_) {
117 if (kv.second != GetSysprop(kv.first)) {
118 __system_property_set(kv.first.c_str(), kv.second.c_str());
119 }
120 }
121 close(flock_fd_);
122 }
123
124 static std::string GetSysprop(const std::string& name) {
125 std::string value;
126 const prop_info* pi = __system_property_find(name.c_str());
127 if (pi == nullptr) return value;
128 __system_property_read_callback(
129 pi,
130 [](void* cookie, const char* /* name */, const char* value, uint32_t /* serial */) {
131 std::string* v = static_cast<std::string*>(cookie);
132 *v = value;
133 },
134 &value);
135 return value;
136 }
137};
138
139TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_enabled) {
140 std::string maps;
141 EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
142 EXPECT_TRUE(maps.find("GWP-ASan") != std::string::npos) << maps;
143
144 volatile int* x = new int;
145 delete x;
146 EXPECT_DEATH({ *x = 7; }, "");
147}
148
149TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_disabled) {
150 std::string maps;
151 EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
152 EXPECT_TRUE(maps.find("GWP-ASan") == std::string::npos);
153}
154
155TEST(gwp_asan_integration, sysprops_program_specific) {
156 SyspropRestorer restorer;
157
158 std::string path = testing::internal::GetArgvs()[0];
159 const char* basename = __gnu_basename(path.c_str());
160 __system_property_set((std::string("libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
161 __system_property_set((std::string("libc.debug.gwp_asan.process_sampling.") + basename).c_str(),
162 "1");
163 __system_property_set((std::string("libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
164 "40000");
165
166 RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
167}
168
169TEST(gwp_asan_integration, sysprops_persist_program_specific) {
170 SyspropRestorer restorer;
171
172 std::string path = testing::internal::GetArgvs()[0];
173 const char* basename = __gnu_basename(path.c_str());
174 __system_property_set(
175 (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
176 __system_property_set(
177 (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
178 __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
179 "40000");
180
181 RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
182}
183
184TEST(gwp_asan_integration, sysprops_system) {
185 SyspropRestorer restorer;
186
187 __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1");
188 __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1");
189 __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "40000");
190
191 RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
192}
193
194TEST(gwp_asan_integration, sysprops_persist_system) {
195 SyspropRestorer restorer;
196
197 __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "1");
198 __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "1");
199 __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "40000");
200
201 RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
202}
203
204TEST(gwp_asan_integration, sysprops_non_persist_overrides_persist) {
205 SyspropRestorer restorer;
206
207 __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1");
208 __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1");
209 __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "40000");
210
211 __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "0");
212 __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "0");
213 __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "0");
214
215 RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
216}
217
218TEST(gwp_asan_integration, sysprops_program_specific_overrides_default) {
219 SyspropRestorer restorer;
220
221 std::string path = testing::internal::GetArgvs()[0];
222 const char* basename = __gnu_basename(path.c_str());
223 __system_property_set(
224 (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
225 __system_property_set(
226 (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
227 __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
228 "40000");
229
230 __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
231 __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
232 __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
233
234 RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
235}
236
237TEST(gwp_asan_integration, sysprops_can_disable) {
238 SyspropRestorer restorer;
239
240 __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
241 __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
242 __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
243
244 RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_disabled");
245}
246
247TEST(gwp_asan_integration, env_overrides_sysprop) {
248 SyspropRestorer restorer;
249
250 __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
251 __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
252 __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
253
254 RunGwpAsanTest("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
255}
256
Mitch Phillipse6997d52020-11-30 15:04:14 -0800257#endif // defined(__BIONIC__)