1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <gtest/gtest.h> 18 19 #if defined(__BIONIC__) 20 #include <android-base/properties.h> 21 #endif 22 23 #include <dlfcn.h> 24 #include <libgen.h> 25 #include <limits.h> 26 #include <stdio.h> 27 #include <stdint.h> 28 #include <sys/stat.h> 29 30 #include <string> 31 #include <iostream> 32 #include <fstream> 33 34 #include "gtest_globals.h" 35 #include <android-base/file.h> 36 #include "utils.h" 37 main_global_default_serial()38 extern "C" int main_global_default_serial() { 39 return 3370318; 40 } 41 main_global_protected_serial()42 extern "C" int main_global_protected_serial() { 43 return 2716057; 44 } 45 46 // The following functions are defined in DT_NEEDED 47 // libdl_preempt_test.so library. 48 49 // This one calls main_global_default_serial 50 extern "C" int main_global_default_get_serial(); 51 52 // This one calls main_global_protected_serial 53 extern "C" int main_global_protected_get_serial(); 54 55 // This one calls lib_global_default_serial 56 extern "C" int lib_global_default_get_serial(); 57 58 // This one calls lib_global_protected_serial 59 extern "C" int lib_global_protected_get_serial(); 60 61 // This test verifies that the global default function 62 // main_global_default_serial() is preempted by 63 // the function defined above. TEST(dl,main_preempts_global_default)64 TEST(dl, main_preempts_global_default) { 65 ASSERT_EQ(3370318, main_global_default_get_serial()); 66 } 67 68 // This one makes sure that the global protected 69 // symbols do not get preempted TEST(dl,main_does_not_preempt_global_protected)70 TEST(dl, main_does_not_preempt_global_protected) { 71 ASSERT_EQ(3370318, main_global_protected_get_serial()); 72 } 73 74 // check same things for lib TEST(dl,lib_preempts_global_default)75 TEST(dl, lib_preempts_global_default) { 76 ASSERT_EQ(3370318, lib_global_default_get_serial()); 77 } 78 TEST(dl,lib_does_not_preempt_global_protected)79 TEST(dl, lib_does_not_preempt_global_protected) { 80 ASSERT_EQ(3370318, lib_global_protected_get_serial()); 81 } 82 83 #if defined(__BIONIC__) 84 #if defined(__LP64__) 85 static constexpr const char* kPathToLinker = "/system/bin/linker64"; 86 #else 87 static constexpr const char* kPathToLinker = "/system/bin/linker"; 88 #endif 89 90 #if defined (__aarch64__) 91 static constexpr const char* kAlternatePathToLinker = "/system/bin/arm64/linker64"; 92 #elif defined (__arm__) 93 static constexpr const char* kAlternatePathToLinker = "/system/bin/arm/linker"; 94 #elif defined (__x86_64__) 95 static constexpr const char* kAlternatePathToLinker = "/system/bin/x86_64/linker64"; 96 #elif defined (__i386__) 97 static constexpr const char* kAlternatePathToLinker = "/system/bin/x86/linker"; 98 #else 99 #error "Unknown architecture" 100 #endif 101 PathToLinker()102 const char* PathToLinker() { 103 // On the systems with emulated architecture linker would be of different 104 // architecture. Try to use alternate paths first. 105 struct stat buffer; 106 if (stat(kAlternatePathToLinker, &buffer) == 0) { 107 return kAlternatePathToLinker; 108 } 109 return kPathToLinker; 110 } 111 #endif // defined(__BIONIC__) 112 TEST(dl,exec_linker)113 TEST(dl, exec_linker) { 114 #if defined(__BIONIC__) 115 const char* path_to_linker = PathToLinker(); 116 std::string usage_prefix = std::string("Usage: ") + path_to_linker; 117 ExecTestHelper eth; 118 eth.SetArgs({ path_to_linker, nullptr }); 119 eth.Run([&]() { execve(path_to_linker, eth.GetArgs(), eth.GetEnv()); }, 0, nullptr); 120 ASSERT_EQ(0u, eth.GetOutput().find(usage_prefix)) << "Test output:\n" << eth.GetOutput(); 121 #endif 122 } 123 TEST(dl,exec_linker_load_file)124 TEST(dl, exec_linker_load_file) { 125 #if defined(__BIONIC__) 126 const char* path_to_linker = PathToLinker(); 127 std::string helper = GetTestlibRoot() + 128 "/exec_linker_helper/exec_linker_helper"; 129 std::string expected_output = 130 "ctor: argc=1 argv[0]=" + helper + "\n" + 131 "main: argc=1 argv[0]=" + helper + "\n" + 132 "__progname=exec_linker_helper\n" + 133 "helper_func called\n"; 134 ExecTestHelper eth; 135 eth.SetArgs({ path_to_linker, helper.c_str(), nullptr }); 136 eth.Run([&]() { execve(path_to_linker, eth.GetArgs(), eth.GetEnv()); }, 0, expected_output.c_str()); 137 #endif 138 } 139 TEST(dl,exec_linker_load_from_zip)140 TEST(dl, exec_linker_load_from_zip) { 141 #if defined(__BIONIC__) 142 const char* path_to_linker = PathToLinker(); 143 std::string helper = GetTestlibRoot() + 144 "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip!/libdir/exec_linker_helper"; 145 std::string expected_output = 146 "ctor: argc=1 argv[0]=" + helper + "\n" + 147 "main: argc=1 argv[0]=" + helper + "\n" + 148 "__progname=exec_linker_helper\n" + 149 "helper_func called\n"; 150 ExecTestHelper eth; 151 eth.SetArgs({ path_to_linker, helper.c_str(), nullptr }); 152 eth.Run([&]() { execve(path_to_linker, eth.GetArgs(), eth.GetEnv()); }, 0, expected_output.c_str()); 153 #endif 154 } 155 TEST(dl,exec_linker_load_self)156 TEST(dl, exec_linker_load_self) { 157 #if defined(__BIONIC__) 158 const char* path_to_linker = PathToLinker(); 159 std::string error_message = "error: linker cannot load itself\n"; 160 ExecTestHelper eth; 161 eth.SetArgs({ path_to_linker, path_to_linker, nullptr }); 162 eth.Run([&]() { execve(path_to_linker, eth.GetArgs(), eth.GetEnv()); }, EXIT_FAILURE, error_message.c_str()); 163 #endif 164 } 165 TEST(dl,preinit_system_calls)166 TEST(dl, preinit_system_calls) { 167 #if defined(__BIONIC__) 168 SKIP_WITH_HWASAN << "hwasan not initialized in preinit_array, b/124007027"; 169 std::string helper = GetTestlibRoot() + 170 "/preinit_syscall_test_helper/preinit_syscall_test_helper"; 171 chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607 172 ExecTestHelper eth; 173 eth.SetArgs({ helper.c_str(), nullptr }); 174 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, nullptr); 175 #endif 176 } 177 TEST(dl,preinit_getauxval)178 TEST(dl, preinit_getauxval) { 179 #if defined(__BIONIC__) 180 SKIP_WITH_HWASAN << "hwasan not initialized in preinit_array, b/124007027"; 181 std::string helper = GetTestlibRoot() + 182 "/preinit_getauxval_test_helper/preinit_getauxval_test_helper"; 183 chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607 184 ExecTestHelper eth; 185 eth.SetArgs({ helper.c_str(), nullptr }); 186 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, nullptr); 187 #else 188 // Force a failure when not compiled for bionic so the test is considered a pass. 189 ASSERT_TRUE(false); 190 #endif 191 } 192 193 TEST(dl,exec_without_ld_preload)194 TEST(dl, exec_without_ld_preload) { 195 #if defined(__BIONIC__) 196 std::string helper = GetTestlibRoot() + 197 "/ld_preload_test_helper/ld_preload_test_helper"; 198 chmod(helper.c_str(), 0755); 199 ExecTestHelper eth; 200 eth.SetArgs({ helper.c_str(), nullptr }); 201 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "12345"); 202 #endif 203 } 204 TEST(dl,exec_with_ld_preload)205 TEST(dl, exec_with_ld_preload) { 206 #if defined(__BIONIC__) 207 std::string helper = GetTestlibRoot() + 208 "/ld_preload_test_helper/ld_preload_test_helper"; 209 std::string env = std::string("LD_PRELOAD=") + GetTestlibRoot() + "/ld_preload_test_helper_lib2.so"; 210 chmod(helper.c_str(), 0755); 211 ExecTestHelper eth; 212 eth.SetArgs({ helper.c_str(), nullptr }); 213 eth.SetEnv({ env.c_str(), nullptr }); 214 // ld_preload_test_helper calls get_value_from_lib() and returns the value. 215 // The symbol is defined by two libs: ld_preload_test_helper_lib.so and 216 // ld_preloaded_lib.so. The former is DT_NEEDED and the latter is LD_PRELOADED 217 // via this execution. The main executable is linked to the LD_PRELOADED lib 218 // and the value given from the lib is returned. 219 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "54321"); 220 #endif 221 } 222 223 224 // ld_config_test_helper must fail because it is depending on a lib which is not 225 // in the search path 226 // 227 // Call sequence is... 228 // _helper -- (get_value_from_lib()) --> 229 // _lib1.so -- (get_value_from_another_lib()) --> 230 // _lib2.so (returns 12345) 231 // The two libs are in ns2/ subdir. TEST(dl,exec_without_ld_config_file)232 TEST(dl, exec_without_ld_config_file) { 233 #if defined(__BIONIC__) 234 std::string error_message = 235 "CANNOT LINK EXECUTABLE \"" + GetTestlibRoot() + 236 "/ld_config_test_helper/ld_config_test_helper\": library \"ld_config_test_helper_lib1.so\" " 237 "not found: needed by main executable\n"; 238 std::string helper = GetTestlibRoot() + 239 "/ld_config_test_helper/ld_config_test_helper"; 240 chmod(helper.c_str(), 0755); 241 ExecTestHelper eth; 242 eth.SetArgs({ helper.c_str(), nullptr }); 243 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, EXIT_FAILURE, error_message.c_str()); 244 #endif 245 } 246 247 #if defined(__BIONIC__) 248 extern "C" void android_get_LD_LIBRARY_PATH(char*, size_t); create_ld_config_file(const char * config_file)249 static void create_ld_config_file(const char* config_file) { 250 char default_search_paths[PATH_MAX]; 251 android_get_LD_LIBRARY_PATH(default_search_paths, sizeof(default_search_paths)); 252 253 std::ofstream fout(config_file, std::ios::out); 254 fout << "dir.test = " << GetTestlibRoot() << "/ld_config_test_helper/" << std::endl 255 << "[test]" << std::endl 256 << "additional.namespaces = ns2" << std::endl 257 << "namespace.default.search.paths = " << GetTestlibRoot() << std::endl 258 << "namespace.default.links = ns2" << std::endl 259 << "namespace.default.link.ns2.shared_libs = libc.so:libm.so:libdl.so:ld_config_test_helper_lib1.so" << std::endl 260 << "namespace.ns2.search.paths = " << default_search_paths << ":" << GetTestlibRoot() << "/ns2" << std::endl; 261 fout.close(); 262 } 263 #endif 264 265 #if defined(__BIONIC__) is_debuggable_build()266 static bool is_debuggable_build() { 267 return android::base::GetBoolProperty("ro.debuggable", false); 268 } 269 #endif 270 271 // _lib1.so and _lib2.so are now searchable by having another namespace 'ns2' 272 // whose search paths include the 'ns2/' subdir. TEST(dl,exec_with_ld_config_file)273 TEST(dl, exec_with_ld_config_file) { 274 #if defined(__BIONIC__) 275 SKIP_WITH_HWASAN << "libclang_rt.hwasan is not found with custom ld config"; 276 if (!is_debuggable_build()) { 277 GTEST_SKIP() << "LD_CONFIG_FILE is not supported on user build"; 278 } 279 std::string helper = GetTestlibRoot() + 280 "/ld_config_test_helper/ld_config_test_helper"; 281 TemporaryFile config_file; 282 create_ld_config_file(config_file.path); 283 std::string env = std::string("LD_CONFIG_FILE=") + config_file.path; 284 chmod(helper.c_str(), 0755); 285 ExecTestHelper eth; 286 eth.SetArgs({ helper.c_str(), nullptr }); 287 eth.SetEnv({ env.c_str(), nullptr }); 288 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "12345"); 289 #endif 290 } 291 292 // _lib3.so has same symbol as lib2.so but returns 54321. _lib3.so is 293 // LD_PRELOADed. This test is to ensure LD_PRELOADed libs are available to 294 // additional namespaces other than the default namespace. TEST(dl,exec_with_ld_config_file_with_ld_preload)295 TEST(dl, exec_with_ld_config_file_with_ld_preload) { 296 #if defined(__BIONIC__) 297 SKIP_WITH_HWASAN << "libclang_rt.hwasan is not found with custom ld config"; 298 if (!is_debuggable_build()) { 299 GTEST_SKIP() << "LD_CONFIG_FILE is not supported on user build"; 300 } 301 std::string helper = GetTestlibRoot() + 302 "/ld_config_test_helper/ld_config_test_helper"; 303 TemporaryFile config_file; 304 create_ld_config_file(config_file.path); 305 std::string env = std::string("LD_CONFIG_FILE=") + config_file.path; 306 std::string env2 = std::string("LD_PRELOAD=") + GetTestlibRoot() + "/ld_config_test_helper_lib3.so"; 307 chmod(helper.c_str(), 0755); 308 ExecTestHelper eth; 309 eth.SetArgs({ helper.c_str(), nullptr }); 310 eth.SetEnv({ env.c_str(), env2.c_str(), nullptr }); 311 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "54321"); 312 #endif 313 } 314 315 // ensures that LD_CONFIG_FILE env var does not work for production builds. 316 // The test input is the same as exec_with_ld_config_file, but it must fail in 317 // this case. TEST(dl,disable_ld_config_file)318 TEST(dl, disable_ld_config_file) { 319 #if defined(__BIONIC__) 320 if (getuid() == 0) { 321 // when executed from the shell (e.g. not as part of CTS), skip the test. 322 // This test is only for CTS. 323 GTEST_SKIP() << "test is not supported with root uid"; 324 } 325 if (is_debuggable_build()) { 326 GTEST_SKIP() << "test is not supported on debuggable build"; 327 } 328 329 std::string error_message = std::string("CANNOT LINK EXECUTABLE ") + 330 "\"" + GetTestlibRoot() + "/ld_config_test_helper/ld_config_test_helper\": " + 331 "library \"ld_config_test_helper_lib1.so\" not found: needed by main executable\n"; 332 std::string helper = GetTestlibRoot() + 333 "/ld_config_test_helper/ld_config_test_helper"; 334 TemporaryFile config_file; 335 create_ld_config_file(config_file.path); 336 std::string env = std::string("LD_CONFIG_FILE=") + config_file.path; 337 chmod(helper.c_str(), 0755); 338 ExecTestHelper eth; 339 eth.SetArgs({ helper.c_str(), nullptr }); 340 eth.SetEnv({ env.c_str(), nullptr }); 341 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, EXIT_FAILURE, error_message.c_str()); 342 #endif 343 } 344 RelocationsTest(const char * lib,const char * expectation)345 static void RelocationsTest(const char* lib, const char* expectation) { 346 #if defined(__BIONIC__) 347 // Does readelf think the .so file looks right? 348 const std::string path = GetTestlibRoot() + "/" + lib; 349 ExecTestHelper eth; 350 eth.SetArgs({ "readelf", "-SW", path.c_str(), nullptr }); 351 eth.Run([&]() { execvpe("readelf", eth.GetArgs(), eth.GetEnv()); }, 0, nullptr); 352 ASSERT_TRUE(eth.GetOutput().find(expectation) != std::string::npos) << eth.GetOutput(); 353 354 // Can we load it? 355 void* handle = dlopen(lib, RTLD_NOW); 356 ASSERT_TRUE(handle != nullptr) << dlerror(); 357 #else 358 UNUSED(lib); 359 UNUSED(expectation); 360 GTEST_SKIP() << "test is not supported on glibc"; 361 #endif 362 } 363 TEST(dl,relocations_RELR)364 TEST(dl, relocations_RELR) { 365 RelocationsTest("librelocations-RELR.so", 366 ".relr.dyn RELR"); 367 } 368 TEST(dl,relocations_ANDROID_RELR)369 TEST(dl, relocations_ANDROID_RELR) { 370 RelocationsTest("librelocations-ANDROID_RELR.so", 371 ".relr.dyn ANDROID_RELR"); 372 } 373 TEST(dl,relocations_ANDROID_REL)374 TEST(dl, relocations_ANDROID_REL) { 375 RelocationsTest("librelocations-ANDROID_REL.so", 376 #if __LP64__ 377 ".rela.dyn ANDROID_RELA" 378 #else 379 ".rel.dyn ANDROID_REL" 380 #endif 381 ); 382 } 383 TEST(dl,relocations_fat)384 TEST(dl, relocations_fat) { 385 RelocationsTest("librelocations-fat.so", 386 #if __LP64__ 387 ".rela.dyn RELA" 388 #else 389 ".rel.dyn REL" 390 #endif 391 ); 392 } 393