1 /* 2 * Copyright (C) 2017 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 <stdlib.h> 30 #include <string.h> 31 #include <sys/mman.h> 32 33 #include <gtest/gtest.h> 34 35 #include "../linker_config.h" 36 37 #include <unistd.h> 38 39 #include <android-base/stringprintf.h> 40 #include <android-base/file.h> 41 #include <android-base/test_utils.h> 42 43 #include "private/ScopeGuard.h" 44 45 46 static const char* config_str = 47 "# comment \n" 48 "dir.test = /data/local/tmp\n" 49 "\n" 50 "[test]\n" 51 "\n" 52 "enable.target.sdk.version = true\n" 53 "additional.namespaces=system\n" 54 "namespace.default.isolated = true\n" 55 "namespace.default.search.paths = /vendor/${LIB}\n" 56 "namespace.default.permitted.paths = /vendor/${LIB}\n" 57 "namespace.default.asan.search.paths = /data:/vendor/${LIB}\n" 58 "namespace.default.asan.permitted.paths = /data:/vendor\n" 59 "namespace.default.links = system\n" 60 "namespace.default.link.system.shared_libs = libc.so:libm.so:libdl.so:libstdc++.so\n" 61 "namespace.system.isolated = true\n" 62 "namespace.system.visible = true\n" 63 "namespace.system.search.paths = /system/${LIB}\n" 64 "namespace.system.permitted.paths = /system/${LIB}\n" 65 "namespace.system.asan.search.paths = /data:/system/${LIB}\n" 66 "namespace.system.asan.permitted.paths = /data:/system\n" 67 "\n"; 68 69 static bool write_version(const std::string& path, uint32_t version) { 70 std::string content = android::base::StringPrintf("%d", version); 71 return android::base::WriteStringToFile(content, path); 72 } 73 74 static void run_linker_config_smoke_test(bool is_asan) { 75 #if defined(__LP64__) 76 const std::vector<std::string> kExpectedDefaultSearchPath = is_asan ? 77 std::vector<std::string>({ "/data", "/vendor/lib64"}) : 78 std::vector<std::string>({ "/vendor/lib64" }); 79 80 const std::vector<std::string> kExpectedDefaultPermittedPath = is_asan ? 81 std::vector<std::string>({ "/data", "/vendor" }) : 82 std::vector<std::string>({ "/vendor/lib64" }); 83 84 const std::vector<std::string> kExpectedSystemSearchPath = is_asan ? 85 std::vector<std::string>({ "/data", "/system/lib64" }) : 86 std::vector<std::string>({ "/system/lib64" }); 87 88 const std::vector<std::string> kExpectedSystemPermittedPath = is_asan ? 89 std::vector<std::string>({ "/data", "/system" }) : 90 std::vector<std::string>({ "/system/lib64" }); 91 #else 92 const std::vector<std::string> kExpectedDefaultSearchPath = is_asan ? 93 std::vector<std::string>({ "/data", "/vendor/lib"}) : 94 std::vector<std::string>({ "/vendor/lib" }); 95 96 const std::vector<std::string> kExpectedDefaultPermittedPath = is_asan ? 97 std::vector<std::string>({ "/data", "/vendor" }) : 98 std::vector<std::string>({ "/vendor/lib" }); 99 100 const std::vector<std::string> kExpectedSystemSearchPath = is_asan ? 101 std::vector<std::string>({ "/data", "/system/lib" }) : 102 std::vector<std::string>({ "/system/lib" }); 103 104 const std::vector<std::string> kExpectedSystemPermittedPath = is_asan ? 105 std::vector<std::string>({ "/data", "/system" }) : 106 std::vector<std::string>({ "/system/lib" }); 107 #endif 108 109 TemporaryFile tmp_file; 110 close(tmp_file.fd); 111 tmp_file.fd = -1; 112 113 android::base::WriteStringToFile(config_str, tmp_file.path); 114 115 TemporaryDir tmp_dir; 116 117 std::string executable_path = std::string(tmp_dir.path) + "/some-binary"; 118 std::string version_file = std::string(tmp_dir.path) + "/.version"; 119 120 auto file_guard = make_scope_guard([&version_file] { 121 unlink(version_file.c_str()); 122 }); 123 124 ASSERT_TRUE(write_version(version_file, 113U)) << strerror(errno); 125 126 // read config 127 const Config* config = nullptr; 128 std::string error_msg; 129 ASSERT_TRUE(Config::read_binary_config(tmp_file.path, 130 executable_path.c_str(), 131 is_asan, 132 &config, 133 &error_msg)) << error_msg; 134 ASSERT_TRUE(config != nullptr); 135 ASSERT_TRUE(error_msg.empty()); 136 137 ASSERT_EQ(113U, config->target_sdk_version()); 138 139 const NamespaceConfig* default_ns_config = config->default_namespace_config(); 140 ASSERT_TRUE(default_ns_config != nullptr); 141 142 ASSERT_TRUE(default_ns_config->isolated()); 143 ASSERT_FALSE(default_ns_config->visible()); 144 ASSERT_EQ(kExpectedDefaultSearchPath, default_ns_config->search_paths()); 145 ASSERT_EQ(kExpectedDefaultPermittedPath, default_ns_config->permitted_paths()); 146 147 const auto& default_ns_links = default_ns_config->links(); 148 ASSERT_EQ(1U, default_ns_links.size()); 149 ASSERT_EQ("system", default_ns_links[0].ns_name()); 150 ASSERT_EQ("libc.so:libm.so:libdl.so:libstdc++.so", default_ns_links[0].shared_libs()); 151 152 auto& ns_configs = config->namespace_configs(); 153 ASSERT_EQ(2U, ns_configs.size()); 154 155 // find second namespace 156 const NamespaceConfig* ns_system = nullptr; 157 for (auto& ns : ns_configs) { 158 std::string ns_name = ns->name(); 159 ASSERT_TRUE(ns_name == "system" || ns_name == "default") 160 << "unexpected ns name: " << ns->name(); 161 162 if (ns_name == "system") { 163 ns_system = ns.get(); 164 } 165 } 166 167 ASSERT_TRUE(ns_system != nullptr) << "system namespace was not found"; 168 169 ASSERT_TRUE(ns_system->isolated()); 170 ASSERT_TRUE(ns_system->visible()); 171 ASSERT_EQ(kExpectedSystemSearchPath, ns_system->search_paths()); 172 ASSERT_EQ(kExpectedSystemPermittedPath, ns_system->permitted_paths()); 173 } 174 175 TEST(linker_config, smoke) { 176 run_linker_config_smoke_test(false); 177 } 178 179 // TODO(b/38114603) revive this test when ld.config.txt is enabled for ASAN mode 180 //TEST(linker_config, asan_smoke) { 181 // run_linker_config_smoke_test(true); 182 //} 183