diff options
author | alk3pInjection <webmaster@raspii.tech> | 2023-04-20 00:08:54 +0800 |
---|---|---|
committer | alk3pInjection <webmaster@raspii.tech> | 2023-04-20 00:08:54 +0800 |
commit | 83c4b714e1bb70736d6a72788af8a823a58460a6 (patch) | |
tree | fffea2c0a13bff32d7dd1fa746eba851be244101 /tests | |
parent | 4511e81f8bcbedde9e23943585fe1b649b1f4623 (diff) | |
parent | 6b3432c3ed7d0221db33011a21ff53aa2ea22da1 (diff) |
Merge tag 'LA.QSSI.13.0.r1-09800-qssi.0' into tachibanatachibana
"LA.QSSI.13.0.r1-09800-qssi.0"
Change-Id: Ib4084f349a37cfbf4c089d375b6b1a3a455bbda7
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Android.bp | 15 | ||||
-rw-r--r-- | tests/gwp_asan_test.cpp | 206 | ||||
-rw-r--r-- | tests/utils.cpp | 55 | ||||
-rw-r--r-- | tests/utils.h | 2 |
4 files changed, 252 insertions, 26 deletions
diff --git a/tests/Android.bp b/tests/Android.bp index a54ffb835..8639cfc0a 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -479,6 +479,7 @@ cc_test_library { "uchar_test.cpp", "unistd_nofortify_test.cpp", "unistd_test.cpp", + "utils.cpp", "utmp_test.cpp", "wchar_test.cpp", "wctype_test.cpp", @@ -598,18 +599,6 @@ cc_test_library { ], } -cc_test_library { - name: "libBionicGwpAsanTests", - defaults: ["bionic_tests_defaults"], - srcs: [ - "gwp_asan_test.cpp", - ], - include_dirs: [ - "bionic/libc", - ], - static_libs: ["libbase"], -} - // ----------------------------------------------------------------------------- // Fortify tests. // ----------------------------------------------------------------------------- @@ -774,7 +763,6 @@ cc_test_library { "libBionicStandardTests", "libBionicElfTlsTests", "libBionicFramePointerTests", - "libBionicGwpAsanTests", "libfortify1-tests-clang", "libfortify1-new-tests-clang", "libfortify2-tests-clang", @@ -876,6 +864,7 @@ cc_defaults { "__cxa_thread_atexit_test.cpp", "gtest_globals.cpp", "gtest_main.cpp", + "gwp_asan_test.cpp", "thread_local_test.cpp", ], diff --git a/tests/gwp_asan_test.cpp b/tests/gwp_asan_test.cpp index b2c7780b1..8e5132304 100644 --- a/tests/gwp_asan_test.cpp +++ b/tests/gwp_asan_test.cpp @@ -28,27 +28,20 @@ #include <gtest/gtest.h> #include <stdio.h> +#include <sys/file.h> #include <string> #if defined(__BIONIC__) +#include "android-base/file.h" #include "gwp_asan/options.h" #include "platform/bionic/malloc.h" +#include "sys/system_properties.h" #include "utils.h" -void RunGwpAsanTest(const char* test_name) { - ExecTestHelper eh; - eh.SetEnv({"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1", "GWP_ASAN_MAX_ALLOCS=40000", - nullptr}); - std::string filter_arg = "--gtest_filter="; - filter_arg += test_name; - std::string exec(testing::internal::GetArgvs()[0]); - eh.SetArgs({exec.c_str(), "--gtest_also_run_disabled_tests", filter_arg.c_str(), nullptr}); - eh.Run([&]() { execve(exec.c_str(), eh.GetArgs(), eh.GetEnv()); }, - /* expected_exit_status */ 0, - // |expected_output_regex|, ensure at least one test ran: - R"(\[ PASSED \] [1-9]+0? test)"); -} +// basename is a mess, use gnu basename explicitly to avoid the need for string +// mutation. +extern "C" const char* __gnu_basename(const char* path); // This file implements "torture testing" under GWP-ASan, where we sample every // single allocation. The upper limit for the number of GWP-ASan allocations in @@ -58,4 +51,191 @@ TEST(gwp_asan_integration, malloc_tests_under_torture) { RunGwpAsanTest("malloc.*:-malloc.mallinfo*"); } +class SyspropRestorer { + private: + std::vector<std::pair<std::string, std::string>> props_to_restore_; + // System properties are global for a device, so the tests that mutate the + // GWP-ASan system properties must be run mutually exclusive. Because + // bionic-unit-tests is run in an isolated gtest fashion (each test is run in + // its own process), we have to use flocks to synchronise between tests. + int flock_fd_; + + public: + SyspropRestorer() { + std::string path = testing::internal::GetArgvs()[0]; + flock_fd_ = open(path.c_str(), O_RDONLY); + EXPECT_NE(flock_fd_, -1) << "failed to open self for a flock"; + EXPECT_NE(flock(flock_fd_, LOCK_EX), -1) << "failed to flock myself"; + + const char* basename = __gnu_basename(path.c_str()); + std::vector<std::string> props = { + std::string("libc.debug.gwp_asan.sample_rate.") + basename, + std::string("libc.debug.gwp_asan.process_sampling.") + basename, + std::string("libc.debug.gwp_asan.max_allocs.") + basename, + "libc.debug.gwp_asan.sample_rate.system_default", + "libc.debug.gwp_asan.sample_rate.app_default", + "libc.debug.gwp_asan.process_sampling.system_default", + "libc.debug.gwp_asan.process_sampling.app_default", + "libc.debug.gwp_asan.max_allocs.system_default", + "libc.debug.gwp_asan.max_allocs.app_default", + }; + + size_t base_props_size = props.size(); + for (size_t i = 0; i < base_props_size; ++i) { + props.push_back("persist." + props[i]); + } + + std::string reset_log; + + for (const std::string& prop : props) { + std::string value = GetSysprop(prop); + props_to_restore_.emplace_back(prop, value); + if (!value.empty()) { + __system_property_set(prop.c_str(), ""); + } + } + } + + ~SyspropRestorer() { + for (const auto& kv : props_to_restore_) { + if (kv.second != GetSysprop(kv.first)) { + __system_property_set(kv.first.c_str(), kv.second.c_str()); + } + } + close(flock_fd_); + } + + static std::string GetSysprop(const std::string& name) { + std::string value; + const prop_info* pi = __system_property_find(name.c_str()); + if (pi == nullptr) return value; + __system_property_read_callback( + pi, + [](void* cookie, const char* /* name */, const char* value, uint32_t /* serial */) { + std::string* v = static_cast<std::string*>(cookie); + *v = value; + }, + &value); + return value; + } +}; + +TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_enabled) { + std::string maps; + EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps)); + EXPECT_TRUE(maps.find("GWP-ASan") != std::string::npos) << maps; + + volatile int* x = new int; + delete x; + EXPECT_DEATH({ *x = 7; }, ""); +} + +TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_disabled) { + std::string maps; + EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps)); + EXPECT_TRUE(maps.find("GWP-ASan") == std::string::npos); +} + +TEST(gwp_asan_integration, sysprops_program_specific) { + SyspropRestorer restorer; + + std::string path = testing::internal::GetArgvs()[0]; + const char* basename = __gnu_basename(path.c_str()); + __system_property_set((std::string("libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1"); + __system_property_set((std::string("libc.debug.gwp_asan.process_sampling.") + basename).c_str(), + "1"); + __system_property_set((std::string("libc.debug.gwp_asan.max_allocs.") + basename).c_str(), + "40000"); + + RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled"); +} + +TEST(gwp_asan_integration, sysprops_persist_program_specific) { + SyspropRestorer restorer; + + std::string path = testing::internal::GetArgvs()[0]; + const char* basename = __gnu_basename(path.c_str()); + __system_property_set( + (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1"); + __system_property_set( + (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1"); + __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(), + "40000"); + + RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled"); +} + +TEST(gwp_asan_integration, sysprops_system) { + SyspropRestorer restorer; + + __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1"); + __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1"); + __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "40000"); + + RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled"); +} + +TEST(gwp_asan_integration, sysprops_persist_system) { + SyspropRestorer restorer; + + __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "1"); + __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "1"); + __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "40000"); + + RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled"); +} + +TEST(gwp_asan_integration, sysprops_non_persist_overrides_persist) { + SyspropRestorer restorer; + + __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1"); + __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1"); + __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "40000"); + + __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "0"); + __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "0"); + __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "0"); + + RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled"); +} + +TEST(gwp_asan_integration, sysprops_program_specific_overrides_default) { + SyspropRestorer restorer; + + std::string path = testing::internal::GetArgvs()[0]; + const char* basename = __gnu_basename(path.c_str()); + __system_property_set( + (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1"); + __system_property_set( + (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1"); + __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(), + "40000"); + + __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0"); + __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0"); + __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0"); + + RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled"); +} + +TEST(gwp_asan_integration, sysprops_can_disable) { + SyspropRestorer restorer; + + __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0"); + __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0"); + __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0"); + + RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_disabled"); +} + +TEST(gwp_asan_integration, env_overrides_sysprop) { + SyspropRestorer restorer; + + __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0"); + __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0"); + __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0"); + + RunGwpAsanTest("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled"); +} + #endif // defined(__BIONIC__) diff --git a/tests/utils.cpp b/tests/utils.cpp new file mode 100644 index 000000000..825883327 --- /dev/null +++ b/tests/utils.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "utils.h" + +void RunGwpAsanTest(const char* test_name) { + ExecTestHelper eh; + eh.SetEnv({"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1", "GWP_ASAN_MAX_ALLOCS=40000", + nullptr}); + std::string filter_arg = "--gtest_filter="; + filter_arg += test_name; + std::string exec(testing::internal::GetArgvs()[0]); + eh.SetArgs({exec.c_str(), "--gtest_also_run_disabled_tests", filter_arg.c_str(), nullptr}); + eh.Run([&]() { execve(exec.c_str(), eh.GetArgs(), eh.GetEnv()); }, + /* expected_exit_status */ 0, + // |expected_output_regex|, ensure at least one test ran: + R"(\[ PASSED \] [1-9][0-9]* test)"); +} + +void RunSubtestNoEnv(const char* test_name) { + ExecTestHelper eh; + std::string filter_arg = "--gtest_filter="; + filter_arg += test_name; + std::string exec(testing::internal::GetArgvs()[0]); + eh.SetArgs({exec.c_str(), "--gtest_also_run_disabled_tests", filter_arg.c_str(), nullptr}); + eh.Run([&]() { execve(exec.c_str(), eh.GetArgs(), eh.GetEnv()); }, + /* expected_exit_status */ 0, + // |expected_output_regex|, ensure at least one test ran: + R"(\[ PASSED \] [1-9]+0? test)"); +} diff --git a/tests/utils.h b/tests/utils.h index 72214c2b9..81869e36a 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -19,6 +19,7 @@ #include <dirent.h> #include <dlfcn.h> #include <fcntl.h> +#include <gtest/gtest.h> #include <inttypes.h> #include <sys/mman.h> #include <sys/prctl.h> @@ -264,6 +265,7 @@ class ExecTestHelper { }; void RunGwpAsanTest(const char* test_name); +void RunSubtestNoEnv(const char* test_name); #endif class FdLeakChecker { |