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