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 29#include <string> 30#include <iostream> 31#include <fstream> 32 33#include "gtest_globals.h" 34#include "utils.h" 35 36extern "C" int main_global_default_serial() { 37 return 3370318; 38} 39 40extern "C" int main_global_protected_serial() { 41 return 2716057; 42} 43 44// The following functions are defined in DT_NEEDED 45// libdl_preempt_test.so library. 46 47// This one calls main_global_default_serial 48extern "C" int main_global_default_get_serial(); 49 50// This one calls main_global_protected_serial 51extern "C" int main_global_protected_get_serial(); 52 53// This one calls lib_global_default_serial 54extern "C" int lib_global_default_get_serial(); 55 56// This one calls lib_global_protected_serial 57extern "C" int lib_global_protected_get_serial(); 58 59// This test verifies that the global default function 60// main_global_default_serial() is preempted by 61// the function defined above. 62TEST(dl, main_preempts_global_default) { 63 ASSERT_EQ(3370318, main_global_default_get_serial()); 64} 65 66// This one makes sure that the global protected 67// symbols do not get preempted 68TEST(dl, main_does_not_preempt_global_protected) { 69 ASSERT_EQ(3370318, main_global_protected_get_serial()); 70} 71 72// check same things for lib 73TEST(dl, lib_preempts_global_default) { 74 ASSERT_EQ(3370318, lib_global_default_get_serial()); 75} 76 77TEST(dl, lib_does_not_preempt_global_protected) { 78 ASSERT_EQ(3370318, lib_global_protected_get_serial()); 79} 80 81TEST(dl, exec_linker) { 82#if defined(__BIONIC__) 83#if defined(__LP64__) 84 static constexpr const char* kPathToLinker = "/system/bin/linker64"; 85#else 86 static constexpr const char* kPathToLinker = "/system/bin/linker"; 87#endif 88 ExecTestHelper eth; 89 std::string expected_output = std::string("This is ") + kPathToLinker + 90 ", the helper program for dynamic executables.\n"; 91 eth.SetArgs( { kPathToLinker, nullptr }); 92 eth.Run([&]() { execve(kPathToLinker, eth.GetArgs(), eth.GetEnv()); }, 0, expected_output.c_str()); 93#endif 94} 95 96TEST(dl, preinit_system_calls) { 97#if defined(__BIONIC__) 98 std::string helper = get_testlib_root() + 99 "/preinit_syscall_test_helper/preinit_syscall_test_helper"; 100 chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607 101 ExecTestHelper eth; 102 eth.SetArgs({ helper.c_str(), nullptr }); 103 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, nullptr); 104#endif 105} 106 107TEST(dl, xfail_preinit_getauxval) { 108#if defined(__BIONIC__) 109 std::string helper = get_testlib_root() + 110 "/preinit_getauxval_test_helper/preinit_getauxval_test_helper"; 111 chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607 112 ExecTestHelper eth; 113 eth.SetArgs({ helper.c_str(), nullptr }); 114 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, nullptr); 115#endif 116} 117 118 119TEST(dl, exec_without_ld_preload) { 120#if defined(__BIONIC__) 121 std::string helper = get_testlib_root() + 122 "/ld_preload_test_helper/ld_preload_test_helper"; 123 chmod(helper.c_str(), 0755); 124 ExecTestHelper eth; 125 eth.SetArgs({ helper.c_str(), nullptr }); 126 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "12345"); 127#endif 128} 129 130TEST(dl, exec_with_ld_preload) { 131#if defined(__BIONIC__) 132 std::string helper = get_testlib_root() + 133 "/ld_preload_test_helper/ld_preload_test_helper"; 134 std::string env = std::string("LD_PRELOAD=") + get_testlib_root() + "/ld_preload_test_helper_lib2.so"; 135 chmod(helper.c_str(), 0755); 136 ExecTestHelper eth; 137 eth.SetArgs({ helper.c_str(), nullptr }); 138 eth.SetEnv({ env.c_str(), nullptr }); 139 // ld_preload_test_helper calls get_value_from_lib() and returns the value. 140 // The symbol is defined by two libs: ld_preload_test_helper_lib.so and 141 // ld_preloaded_lib.so. The former is DT_NEEDED and the latter is LD_PRELOADED 142 // via this execution. The main executable is linked to the LD_PRELOADED lib 143 // and the value given from the lib is returned. 144 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "54321"); 145#endif 146} 147 148 149// ld_config_test_helper must fail because it is depending on a lib which is not 150// in the search path 151// 152// Call sequence is... 153// _helper -- (get_value_from_lib()) --> 154// _lib1.so -- (get_value_from_another_lib()) --> 155// _lib2.so (returns 12345) 156// The two libs are in ns2/ subdir. 157TEST(dl, exec_without_ld_config_file) { 158#if defined(__BIONIC__) 159 std::string error_message = "CANNOT LINK EXECUTABLE \"" + get_testlib_root() + "/ld_config_test_helper/ld_config_test_helper\": library \"ld_config_test_helper_lib1.so\" not found\n"; 160 std::string helper = get_testlib_root() + 161 "/ld_config_test_helper/ld_config_test_helper"; 162 chmod(helper.c_str(), 0755); 163 ExecTestHelper eth; 164 eth.SetArgs({ helper.c_str(), nullptr }); 165 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, -6, error_message.c_str()); 166#endif 167} 168 169#if defined(__BIONIC__) 170static void create_ld_config_file(std::string& config_file) { 171 std::ofstream fout(config_file.c_str(), std::ios::out); 172 fout << "dir.test = " << get_testlib_root() << "/ld_config_test_helper/" << std::endl 173 << "[test]" << std::endl 174 << "additional.namespaces = ns2" << std::endl 175 << "namespace.default.search.paths = " << get_testlib_root() << std::endl 176 << "namespace.default.links = ns2" << std::endl 177 << "namespace.default.link.ns2.shared_libs = libc.so:libm.so:libdl.so:ld_config_test_helper_lib1.so" << std::endl 178 << "namespace.ns2.search.paths = /system/${LIB}:" << get_testlib_root() << "/ns2" << std::endl; 179 fout.close(); 180} 181#endif 182 183#if defined(__BIONIC__) 184static bool is_user_build() { 185 std::string build_type = android::base::GetProperty("ro.build.type", "user"); 186 if (build_type == "userdebug" || build_type == "eng") { 187 return false; 188 } 189 return true; 190} 191#endif 192 193// _lib1.so and _lib2.so are now searchable by having another namespace 'ns2' 194// whose search paths include the 'ns2/' subdir. 195TEST(dl, exec_with_ld_config_file) { 196#if defined(__BIONIC__) 197 if (is_user_build()) { 198 // LD_CONFIG_FILE is not supported on user build 199 return; 200 } 201 std::string helper = get_testlib_root() + 202 "/ld_config_test_helper/ld_config_test_helper"; 203 std::string config_file = get_testlib_root() + "/ld.config.txt"; 204 create_ld_config_file(config_file); 205 std::string env = std::string("LD_CONFIG_FILE=") + config_file; 206 chmod(helper.c_str(), 0755); 207 ExecTestHelper eth; 208 eth.SetArgs({ helper.c_str(), nullptr }); 209 eth.SetEnv({ env.c_str(), nullptr }); 210 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "12345"); 211#endif 212} 213 214// _lib3.so has same symbol as lib2.so but returns 54321. _lib3.so is 215// LD_PRELOADed. This test is to ensure LD_PRELOADed libs are available to 216// additional namespaces other than the default namespace. 217TEST(dl, exec_with_ld_config_file_with_ld_preload) { 218#if defined(__BIONIC__) 219 if (is_user_build()) { 220 // LD_CONFIG_FILE is not supported on user build 221 return; 222 } 223 std::string helper = get_testlib_root() + 224 "/ld_config_test_helper/ld_config_test_helper"; 225 std::string config_file = get_testlib_root() + "/ld.config.txt"; 226 create_ld_config_file(config_file); 227 std::string env = std::string("LD_CONFIG_FILE=") + config_file; 228 std::string env2 = std::string("LD_PRELOAD=") + get_testlib_root() + "/ld_config_test_helper_lib3.so"; 229 chmod(helper.c_str(), 0755); 230 ExecTestHelper eth; 231 eth.SetArgs({ helper.c_str(), nullptr }); 232 eth.SetEnv({ env.c_str(), env2.c_str(), nullptr }); 233 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "54321"); 234#endif 235} 236 237// ensures that LD_CONFIG_FILE env var does not work for production builds. 238// The test input is the same as exec_with_ld_config_file, but it must fail in 239// this case. 240TEST(dl, disable_ld_config_file) { 241#if defined(__BIONIC__) 242 if (getuid() == 0) { 243 // when executed from the shell (e.g. not as part of CTS), skip the test. 244 // This test is only for CTS. 245 return; 246 } 247 if (!is_user_build()) { 248 // Skip the test for non production devices 249 return; 250 } 251 252 std::string error_message = "CANNOT LINK EXECUTABLE \"" + get_testlib_root() + "/ld_config_test_helper/ld_config_test_helper\": library \"ld_config_test_helper_lib1.so\" not found\n"; 253 std::string helper = get_testlib_root() + 254 "/ld_config_test_helper/ld_config_test_helper"; 255 std::string config_file = get_testlib_root() + "/ld.config.txt"; 256 create_ld_config_file(config_file); 257 std::string env = std::string("LD_CONFIG_FILE=") + config_file; 258 chmod(helper.c_str(), 0755); 259 ExecTestHelper eth; 260 eth.SetArgs({ helper.c_str(), nullptr }); 261 eth.SetEnv({ env.c_str(), nullptr }); 262 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, -6, error_message.c_str()); 263#endif 264} 265