1 /* 2 * Copyright (C) 2018 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 <errno.h> 30 #include <fcntl.h> 31 #include <poll.h> 32 #include <signal.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <sys/types.h> 36 #include <sys/wait.h> 37 #include <time.h> 38 #include <unistd.h> 39 40 #include <android-base/stringprintf.h> 41 #include <gtest/gtest.h> 42 #include <log/log.h> 43 44 #include <string> 45 #include <thread> 46 #include <vector> 47 48 #include "private/bionic_malloc.h" 49 50 static constexpr time_t kTimeoutSeconds = 10; 51 52 static void Exec(const char* test_name, const char* debug_options, pid_t* pid, int exit_code = 0, 53 time_t timeout_seconds = kTimeoutSeconds) { 54 int fds[2]; 55 ASSERT_NE(-1, pipe(fds)); 56 ASSERT_NE(-1, fcntl(fds[0], F_SETFL, O_NONBLOCK)); 57 if ((*pid = fork()) == 0) { 58 ASSERT_EQ(0, setenv("LIBC_DEBUG_MALLOC_OPTIONS", debug_options, 1)); 59 close(fds[0]); 60 close(STDIN_FILENO); 61 close(STDOUT_FILENO); 62 close(STDERR_FILENO); 63 ASSERT_NE(0, dup2(fds[1], STDOUT_FILENO)); 64 ASSERT_NE(0, dup2(fds[1], STDERR_FILENO)); 65 66 std::vector<const char*> args; 67 // Get a copy of this argument so it doesn't disappear on us. 68 std::string exec(testing::internal::GetArgvs()[0]); 69 args.push_back(exec.c_str()); 70 args.push_back("--gtest_also_run_disabled_tests"); 71 std::string filter_arg = std::string("--gtest_filter=") + test_name; 72 args.push_back(filter_arg.c_str()); 73 args.push_back(nullptr); 74 execv(args[0], reinterpret_cast<char* const*>(const_cast<char**>(args.data()))); 75 exit(20); 76 } 77 ASSERT_NE(-1, *pid); 78 close(fds[1]); 79 80 std::string output; 81 std::vector<char> buffer(4096); 82 time_t start_time = time(nullptr); 83 bool done = false; 84 while (true) { 85 struct pollfd read_fd = {.fd = fds[0], .events = POLLIN}; 86 if (TEMP_FAILURE_RETRY(poll(&read_fd, 1, 1)) > 0) { 87 ssize_t bytes = TEMP_FAILURE_RETRY(read(fds[0], buffer.data(), sizeof(buffer) - 1)); 88 if (bytes == -1 && errno == EAGAIN) { 89 continue; 90 } 91 ASSERT_NE(-1, bytes); 92 if (bytes == 0) { 93 done = true; 94 break; 95 } 96 output.append(buffer.data(), bytes); 97 } 98 99 if ((time(nullptr) - start_time) > timeout_seconds) { 100 kill(*pid, SIGINT); 101 break; 102 } 103 } 104 EXPECT_TRUE(done) << "Timed out while reading data, output:\n" << output; 105 106 done = false; 107 int status; 108 start_time = time(nullptr); 109 while (true) { 110 int wait_pid = waitpid(*pid, &status, WNOHANG); 111 if (*pid == wait_pid) { 112 done = true; 113 break; 114 } 115 if ((time(nullptr) - start_time) > timeout_seconds) { 116 break; 117 } 118 } 119 if (!done) { 120 kill(*pid, SIGKILL); 121 start_time = time(nullptr); 122 while (true) { 123 int kill_status; 124 int wait_pid = waitpid(*pid, &kill_status, WNOHANG); 125 if (wait_pid == *pid || (time(nullptr) - start_time) > timeout_seconds) { 126 break; 127 } 128 } 129 } 130 131 ASSERT_TRUE(done) << "Timed out waiting for waitpid, output:\n" << output; 132 ASSERT_FALSE(WIFSIGNALED(status)) 133 << "Failed with signal " << WTERMSIG(status) << "\nOutput:\n" << output; 134 ASSERT_EQ(exit_code, WEXITSTATUS(status)) << "Output:\n" << output; 135 } 136 137 static void GetLogStr(pid_t pid, std::string* log_str, log_id log = LOG_ID_MAIN) { 138 log_str->clear(); 139 140 logger_list* list; 141 list = android_logger_list_open(log, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid); 142 ASSERT_TRUE(list != nullptr); 143 144 while (true) { 145 log_msg msg; 146 ssize_t actual = android_logger_list_read(list, &msg); 147 if (actual < 0) { 148 if (actual == -EINTR) { 149 // Interrupted retry. 150 continue; 151 } else if (actual == -EAGAIN) { 152 // Non-blocking EOF, finished. 153 break; 154 } else { 155 break; 156 } 157 } else if (actual == 0) { 158 break; 159 } 160 ASSERT_EQ(msg.entry.pid, pid); 161 162 char* msg_str = msg.msg(); 163 if (msg_str != nullptr) { 164 char* tag = msg_str + 1; 165 msg_str = tag + strlen(tag) + 1; 166 *log_str += msg_str; 167 if (log_str->back() != '\n') { 168 *log_str += '\n'; 169 } 170 } 171 } 172 173 android_logger_list_close(list); 174 } 175 176 static void FindStrings(pid_t pid, std::vector<const char*> match_strings, 177 time_t timeout_seconds = kTimeoutSeconds) { 178 std::string log_str; 179 time_t start = time(nullptr); 180 bool found_all; 181 while (true) { 182 GetLogStr(pid, &log_str); 183 found_all = true; 184 for (auto str : match_strings) { 185 if (log_str.find(str) == std::string::npos) { 186 found_all = false; 187 break; 188 } 189 } 190 if (found_all) { 191 return; 192 } 193 if ((time(nullptr) - start) > timeout_seconds) { 194 break; 195 } 196 } 197 ASSERT_TRUE(found_all) << "Didn't find expected log output:\n" + log_str; 198 } 199 200 TEST(MallocTests, DISABLED_smoke) {} 201 202 TEST(MallocDebugSystemTest, smoke) { 203 pid_t pid; 204 ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_smoke", "verbose backtrace", &pid)); 205 206 ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"})); 207 } 208 209 static void SetAllocationLimit() { 210 // Set to a large value, this is only to enable the limit code and 211 // verify that malloc debug is still called properly. 212 size_t limit = 500 * 1024 * 1024; 213 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit))); 214 } 215 216 static void AlignedAlloc() { 217 void* ptr = aligned_alloc(64, 1152); 218 ASSERT_TRUE(ptr != nullptr); 219 memset(ptr, 0, 1152); 220 } 221 222 TEST(MallocTests, DISABLED_leak_memory_aligned_alloc) { 223 AlignedAlloc(); 224 } 225 226 TEST(MallocTests, DISABLED_leak_memory_limit_aligned_alloc) { 227 SetAllocationLimit(); 228 AlignedAlloc(); 229 } 230 231 static void Calloc() { 232 void* ptr = calloc(1, 1123); 233 ASSERT_TRUE(ptr != nullptr); 234 memset(ptr, 1, 1123); 235 } 236 237 TEST(MallocTests, DISABLED_leak_memory_calloc) { 238 Calloc(); 239 } 240 241 TEST(MallocTests, DISABLED_leak_memory_limit_calloc) { 242 SetAllocationLimit(); 243 Calloc(); 244 } 245 246 static void Malloc() { 247 void* ptr = malloc(1123); 248 ASSERT_TRUE(ptr != nullptr); 249 memset(ptr, 0, 1123); 250 } 251 252 TEST(MallocTests, DISABLED_leak_memory_malloc) { 253 Malloc(); 254 } 255 256 TEST(MallocTests, DISABLED_leak_memory_limit_malloc) { 257 SetAllocationLimit(); 258 Malloc(); 259 } 260 261 static void Memalign() { 262 void* ptr = memalign(64, 1123); 263 ASSERT_TRUE(ptr != nullptr); 264 memset(ptr, 0, 1123); 265 } 266 267 TEST(MallocTests, DISABLED_leak_memory_memalign) { 268 Memalign(); 269 } 270 271 TEST(MallocTests, DISABLED_leak_memory_limit_memalign) { 272 SetAllocationLimit(); 273 Memalign(); 274 } 275 276 static void PosixMemalign() { 277 void* ptr; 278 ASSERT_EQ(0, posix_memalign(&ptr, 64, 1123)); 279 ASSERT_TRUE(ptr != nullptr); 280 memset(ptr, 0, 1123); 281 } 282 283 TEST(MallocTests, DISABLED_leak_memory_posix_memalign) { 284 PosixMemalign(); 285 } 286 287 TEST(MallocTests, DISABLED_leak_memory_limit_posix_memalign) { 288 SetAllocationLimit(); 289 PosixMemalign(); 290 } 291 292 static void Reallocarray() { 293 void* ptr = reallocarray(nullptr, 1, 1123); 294 ASSERT_TRUE(ptr != nullptr); 295 memset(ptr, 0, 1123); 296 } 297 298 TEST(MallocTests, DISABLED_leak_memory_reallocarray) { 299 Reallocarray(); 300 } 301 302 TEST(MallocTests, DISABLED_leak_memory_limit_reallocarray) { 303 SetAllocationLimit(); 304 Reallocarray(); 305 } 306 307 static void Realloc() { 308 void* ptr = realloc(nullptr, 1123); 309 ASSERT_TRUE(ptr != nullptr); 310 memset(ptr, 0, 1123); 311 } 312 313 TEST(MallocTests, DISABLED_leak_memory_realloc) { 314 Realloc(); 315 } 316 317 TEST(MallocTests, DISABLED_leak_memory_limit_realloc) { 318 SetAllocationLimit(); 319 Realloc(); 320 } 321 322 #if !defined(__LP64__) 323 extern "C" void* pvalloc(size_t); 324 325 static void Pvalloc() { 326 void* ptr = pvalloc(1123); 327 ASSERT_TRUE(ptr != nullptr); 328 memset(ptr, 0, 1123); 329 } 330 331 TEST(MallocTests, DISABLED_leak_memory_pvalloc) { 332 Pvalloc(); 333 } 334 335 TEST(MallocTests, DISABLED_leak_memory_limit_pvalloc) { 336 SetAllocationLimit(); 337 Pvalloc(); 338 } 339 340 extern "C" void* valloc(size_t); 341 342 static void Valloc() { 343 void* ptr = valloc(1123); 344 ASSERT_TRUE(ptr != nullptr); 345 memset(ptr, 0, 1123); 346 } 347 348 TEST(MallocTests, DISABLED_leak_memory_valloc) { 349 Valloc(); 350 } 351 352 TEST(MallocTests, DISABLED_leak_memory_limit_valloc) { 353 SetAllocationLimit(); 354 Valloc(); 355 } 356 #endif 357 358 static void VerifyLeak(const char* test_prefix) { 359 struct FunctionInfo { 360 const char* name; 361 size_t size; 362 }; 363 static FunctionInfo functions[] = { 364 { 365 "aligned_alloc", 366 1152, 367 }, 368 { 369 "calloc", 370 1123, 371 }, 372 { 373 "malloc", 374 1123, 375 }, 376 { 377 "memalign", 378 1123, 379 }, 380 { 381 "posix_memalign", 382 1123, 383 }, 384 { 385 "reallocarray", 386 1123, 387 }, 388 { 389 "realloc", 390 1123, 391 }, 392 #if !defined(__LP64__) 393 { 394 "pvalloc", 395 4096, 396 }, 397 { 398 "valloc", 399 1123, 400 } 401 #endif 402 }; 403 404 for (size_t i = 0; i < sizeof(functions) / sizeof(FunctionInfo); i++) { 405 pid_t pid; 406 SCOPED_TRACE(testing::Message() << functions[i].name << " expected size " << functions[i].size); 407 std::string test = std::string("MallocTests.DISABLED_") + test_prefix + functions[i].name; 408 EXPECT_NO_FATAL_FAILURE(Exec(test.c_str(), "verbose backtrace leak_track", &pid)); 409 410 std::string expected_leak = android::base::StringPrintf("leaked block of size %zu at", functions[i].size); 411 EXPECT_NO_FATAL_FAILURE(FindStrings( 412 pid, std::vector<const char*>{"malloc debug enabled", expected_leak.c_str()})); 413 } 414 } 415 416 TEST(MallocDebugSystemTest, verify_leak) { 417 VerifyLeak("leak_memory_"); 418 } 419 420 TEST(MallocDebugSystemTest, verify_leak_allocation_limit) { 421 VerifyLeak("leak_memory_limit_"); 422 } 423 424 static constexpr int kExpectedExitCode = 30; 425 426 TEST(MallocTests, DISABLED_exit_while_threads_allocating) { 427 std::atomic_uint32_t thread_mask; 428 thread_mask = 0; 429 430 for (size_t i = 0; i < 32; i++) { 431 std::thread malloc_thread([&thread_mask, i] { 432 while (true) { 433 void* ptr = malloc(100); 434 if (ptr == nullptr) { 435 exit(1000); 436 } 437 free(ptr); 438 thread_mask.fetch_or(1 << i); 439 } 440 }); 441 malloc_thread.detach(); 442 } 443 444 // Wait until each thread has done at least one allocation. 445 while (thread_mask.load() != 0xffffffff) 446 ; 447 exit(kExpectedExitCode); 448 } 449 450 // Verify that exiting while other threads are doing malloc operations, 451 // that there are no crashes. 452 TEST(MallocDebugSystemTest, exit_while_threads_allocating) { 453 for (size_t i = 0; i < 100; i++) { 454 SCOPED_TRACE(::testing::Message() << "Run " << i); 455 pid_t pid; 456 ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_exit_while_threads_allocating", 457 "verbose backtrace", &pid, kExpectedExitCode)); 458 459 ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"})); 460 461 std::string log_str; 462 GetLogStr(pid, &log_str, LOG_ID_CRASH); 463 ASSERT_TRUE(log_str.find("Fatal signal") == std::string::npos) 464 << "Found crash in log.\nLog message: " << log_str; 465 } 466 } 467