blob: 709a939d2167a79ba6c1dfc84a298a214a261fbe [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 Ferris15c22cd2023-07-24 17:42:17 -070037#include "android-base/silent_death_test.h"
Christopher Ferris8ab38e22023-02-06 18:57:18 -080038#include "android-base/test_utils.h"
Mitch Phillipse6997d52020-11-30 15:04:14 -080039#include "gwp_asan/options.h"
40#include "platform/bionic/malloc.h"
Mitch Phillips9634c362022-06-23 11:07:00 -070041#include "sys/system_properties.h"
Mitch Phillipse6997d52020-11-30 15:04:14 -080042#include "utils.h"
43
Christopher Ferris15c22cd2023-07-24 17:42:17 -070044using gwp_asan_integration_DeathTest = SilentDeathTest;
45
Mitch Phillips9634c362022-06-23 11:07:00 -070046// basename is a mess, use gnu basename explicitly to avoid the need for string
47// mutation.
48extern "C" const char* __gnu_basename(const char* path);
Mitch Phillipse6997d52020-11-30 15:04:14 -080049
Mitch Phillips1f3c8d62022-07-11 09:31:41 -070050// GWP-ASan tests can run much slower, especially when combined with HWASan.
51// Triple the deadline to avoid flakes (b/238585984).
52extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
53 static const char* initial_args[] = {"--deadline_threshold_ms=270000"};
54 *args = initial_args;
55 *num_args = 1;
56 return true;
57}
58
Mitch Phillipse6997d52020-11-30 15:04:14 -080059// This file implements "torture testing" under GWP-ASan, where we sample every
60// single allocation. The upper limit for the number of GWP-ASan allocations in
61// the torture mode is is generally 40,000, so that svelte devices don't
62// explode, as this uses ~163MiB RAM (4KiB per live allocation).
63TEST(gwp_asan_integration, malloc_tests_under_torture) {
Christopher Ferris92a4d2b2023-03-02 21:45:31 +000064 // Do not override HWASan with GWP ASan.
65 SKIP_WITH_HWASAN;
66
67 RunGwpAsanTest("malloc.*:-malloc.mallinfo*");
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
Christopher Ferris15c22cd2023-07-24 17:42:17 -0700139TEST_F(gwp_asan_integration_DeathTest, DISABLED_assert_gwp_asan_enabled) {
Mitch Phillips9634c362022-06-23 11:07:00 -0700140 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
Mitch Phillipsc59d5cc2023-03-27 14:34:36 +0000149// A weaker version of the above tests, only checking that GWP-ASan is enabled
150// for any pointer, not *our* pointer. This allows us to test the system_default
151// sysprops without potentially OOM-ing other random processes:
152// b/273904016#comment5
153TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_enabled_weaker) {
154 std::string maps;
155 EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
156 EXPECT_TRUE(maps.find("GWP-ASan") != std::string::npos) << maps;
157}
158
Mitch Phillips9634c362022-06-23 11:07:00 -0700159TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_disabled) {
160 std::string maps;
161 EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
162 EXPECT_TRUE(maps.find("GWP-ASan") == std::string::npos);
163}
164
165TEST(gwp_asan_integration, sysprops_program_specific) {
Christopher Ferris92a4d2b2023-03-02 21:45:31 +0000166 // Do not override HWASan with GWP ASan.
167 SKIP_WITH_HWASAN;
168
Mitch Phillips9634c362022-06-23 11:07:00 -0700169 SyspropRestorer restorer;
170
171 std::string path = testing::internal::GetArgvs()[0];
172 const char* basename = __gnu_basename(path.c_str());
173 __system_property_set((std::string("libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
174 __system_property_set((std::string("libc.debug.gwp_asan.process_sampling.") + basename).c_str(),
175 "1");
176 __system_property_set((std::string("libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
177 "40000");
178
Christopher Ferris15c22cd2023-07-24 17:42:17 -0700179 RunSubtestNoEnv("gwp_asan_integration_DeathTest.DISABLED_assert_gwp_asan_enabled");
Mitch Phillips9634c362022-06-23 11:07:00 -0700180}
181
182TEST(gwp_asan_integration, sysprops_persist_program_specific) {
Christopher Ferris92a4d2b2023-03-02 21:45:31 +0000183 // Do not override HWASan with GWP ASan.
184 SKIP_WITH_HWASAN;
185
Mitch Phillips9634c362022-06-23 11:07:00 -0700186 SyspropRestorer restorer;
187
188 std::string path = testing::internal::GetArgvs()[0];
189 const char* basename = __gnu_basename(path.c_str());
190 __system_property_set(
191 (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
192 __system_property_set(
193 (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
194 __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
195 "40000");
196
Christopher Ferris15c22cd2023-07-24 17:42:17 -0700197 RunSubtestNoEnv("gwp_asan_integration_DeathTest.DISABLED_assert_gwp_asan_enabled");
Mitch Phillips9634c362022-06-23 11:07:00 -0700198}
199
Mitch Phillips9634c362022-06-23 11:07:00 -0700200TEST(gwp_asan_integration, sysprops_non_persist_overrides_persist) {
Christopher Ferris92a4d2b2023-03-02 21:45:31 +0000201 // Do not override HWASan with GWP ASan.
202 SKIP_WITH_HWASAN;
203
Mitch Phillips9634c362022-06-23 11:07:00 -0700204 SyspropRestorer restorer;
205
206 __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1");
207 __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1");
Mitch Phillipsc59d5cc2023-03-27 14:34:36 +0000208 // Note, any processes launched elsewhere on the system right now will have
209 // GWP-ASan enabled. Make sure that we only use a single slot, otherwise we
210 // could end up causing said badly-timed processes to use up to 163MiB extra
211 // penalty that 40,000 allocs would cause. See b/273904016#comment5 for more
212 // context.
213 __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "1");
Mitch Phillips9634c362022-06-23 11:07:00 -0700214
215 __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "0");
216 __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "0");
217 __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "0");
218
Mitch Phillipsc59d5cc2023-03-27 14:34:36 +0000219 RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled_weaker");
Mitch Phillips9634c362022-06-23 11:07:00 -0700220}
221
222TEST(gwp_asan_integration, sysprops_program_specific_overrides_default) {
Christopher Ferris92a4d2b2023-03-02 21:45:31 +0000223 // Do not override HWASan with GWP ASan.
224 SKIP_WITH_HWASAN;
225
Mitch Phillips9634c362022-06-23 11:07:00 -0700226 SyspropRestorer restorer;
227
228 std::string path = testing::internal::GetArgvs()[0];
229 const char* basename = __gnu_basename(path.c_str());
230 __system_property_set(
231 (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
232 __system_property_set(
233 (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
234 __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
235 "40000");
236
237 __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
238 __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
239 __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
240
Christopher Ferris15c22cd2023-07-24 17:42:17 -0700241 RunSubtestNoEnv("gwp_asan_integration_DeathTest.DISABLED_assert_gwp_asan_enabled");
Mitch Phillips9634c362022-06-23 11:07:00 -0700242}
243
244TEST(gwp_asan_integration, sysprops_can_disable) {
Christopher Ferris92a4d2b2023-03-02 21:45:31 +0000245 // Do not override HWASan with GWP ASan.
246 SKIP_WITH_HWASAN;
247
Mitch Phillips9634c362022-06-23 11:07:00 -0700248 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 RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_disabled");
255}
256
257TEST(gwp_asan_integration, env_overrides_sysprop) {
Christopher Ferris92a4d2b2023-03-02 21:45:31 +0000258 // Do not override HWASan with GWP ASan.
259 SKIP_WITH_HWASAN;
260
Mitch Phillips9634c362022-06-23 11:07:00 -0700261 SyspropRestorer restorer;
262
263 __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
264 __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
265 __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
266
Christopher Ferris15c22cd2023-07-24 17:42:17 -0700267 RunGwpAsanTest("gwp_asan_integration_DeathTest.DISABLED_assert_gwp_asan_enabled");
Mitch Phillips9634c362022-06-23 11:07:00 -0700268}
269
Mitch Phillipse6997d52020-11-30 15:04:14 -0800270#endif // defined(__BIONIC__)