blob: 25341f42b0ec316eea7c34159c5ab385f0ecf7c8 [file] [log] [blame]
Dmitriy Ivanov0416d882014-11-04 09:38:18 -08001/*
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
Jiyong Park4945d8f2017-08-30 11:30:53 +090019#if defined(__BIONIC__)
20#include <android-base/properties.h>
21#endif
22
Dmitriy Ivanov0416d882014-11-04 09:38:18 -080023#include <dlfcn.h>
24#include <libgen.h>
25#include <limits.h>
26#include <stdio.h>
27#include <stdint.h>
28
29#include <string>
Jiyong Park02586a22017-05-20 01:01:24 +090030#include <iostream>
31#include <fstream>
Dmitriy Ivanov0416d882014-11-04 09:38:18 -080032
Elliott Hugheseb04ed52017-03-29 13:48:02 -070033#include "gtest_globals.h"
Ryan Prichard0044cd12018-04-03 20:03:12 -070034#include "TemporaryFile.h"
Dimitry Ivanov2a6955e2017-02-23 11:53:43 -080035#include "utils.h"
36
Dmitriy Ivanov0416d882014-11-04 09:38:18 -080037extern "C" int main_global_default_serial() {
38 return 3370318;
39}
40
41extern "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
49extern "C" int main_global_default_get_serial();
50
51// This one calls main_global_protected_serial
52extern "C" int main_global_protected_get_serial();
53
54// This one calls lib_global_default_serial
55extern "C" int lib_global_default_get_serial();
56
57// This one calls lib_global_protected_serial
58extern "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.
63TEST(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
69TEST(dl, main_does_not_preempt_global_protected) {
70 ASSERT_EQ(3370318, main_global_protected_get_serial());
71}
72
73// check same things for lib
74TEST(dl, lib_preempts_global_default) {
75 ASSERT_EQ(3370318, lib_global_default_get_serial());
76}
77
78TEST(dl, lib_does_not_preempt_global_protected) {
79 ASSERT_EQ(3370318, lib_global_protected_get_serial());
80}
81
Dimitry Ivanov2a6955e2017-02-23 11:53:43 -080082TEST(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
Elliott Hugheseb04ed52017-03-29 13:48:02 -070097TEST(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
108TEST(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
Jiyong Park02586a22017-05-20 01:01:24 +0900119
120TEST(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
131TEST(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.
158TEST(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 });
dimitry04f7a792017-09-29 11:52:17 +0200166 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, EXIT_FAILURE, error_message.c_str());
Jiyong Park02586a22017-05-20 01:01:24 +0900167#endif
168}
169
170#if defined(__BIONIC__)
dimitry1280cf52018-05-09 14:37:47 +0200171extern "C" void android_get_LD_LIBRARY_PATH(char*, size_t);
Ryan Prichard0044cd12018-04-03 20:03:12 -0700172static void create_ld_config_file(const char* config_file) {
dimitry1280cf52018-05-09 14:37:47 +0200173 char default_search_paths[PATH_MAX];
174 android_get_LD_LIBRARY_PATH(default_search_paths, sizeof(default_search_paths));
175
Ryan Prichard0044cd12018-04-03 20:03:12 -0700176 std::ofstream fout(config_file, std::ios::out);
Jiyong Park02586a22017-05-20 01:01:24 +0900177 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
dimitry1280cf52018-05-09 14:37:47 +0200183 << "namespace.ns2.search.paths = " << default_search_paths << ":" << get_testlib_root() << "/ns2" << std::endl;
Jiyong Park02586a22017-05-20 01:01:24 +0900184 fout.close();
185}
186#endif
187
Jiyong Park41704cd2017-09-19 09:48:07 +0900188#if defined(__BIONIC__)
dimitry59d30622017-10-18 13:23:08 +0200189static bool is_debuggable_build() {
190 return android::base::GetBoolProperty("ro.debuggable", false);
Jiyong Park41704cd2017-09-19 09:48:07 +0900191}
192#endif
Jiyong Park02586a22017-05-20 01:01:24 +0900193
194// _lib1.so and _lib2.so are now searchable by having another namespace 'ns2'
195// whose search paths include the 'ns2/' subdir.
196TEST(dl, exec_with_ld_config_file) {
197#if defined(__BIONIC__)
dimitry59d30622017-10-18 13:23:08 +0200198 if (!is_debuggable_build()) {
Jiyong Park41704cd2017-09-19 09:48:07 +0900199 // LD_CONFIG_FILE is not supported on user build
200 return;
201 }
Jiyong Park02586a22017-05-20 01:01:24 +0900202 std::string helper = get_testlib_root() +
203 "/ld_config_test_helper/ld_config_test_helper";
Ryan Prichard0044cd12018-04-03 20:03:12 -0700204 TemporaryFile config_file;
205 create_ld_config_file(config_file.filename);
206 std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
Jiyong Park02586a22017-05-20 01:01:24 +0900207 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.
218TEST(dl, exec_with_ld_config_file_with_ld_preload) {
219#if defined(__BIONIC__)
dimitry59d30622017-10-18 13:23:08 +0200220 if (!is_debuggable_build()) {
Jiyong Park41704cd2017-09-19 09:48:07 +0900221 // LD_CONFIG_FILE is not supported on user build
222 return;
223 }
Jiyong Park02586a22017-05-20 01:01:24 +0900224 std::string helper = get_testlib_root() +
225 "/ld_config_test_helper/ld_config_test_helper";
Ryan Prichard0044cd12018-04-03 20:03:12 -0700226 TemporaryFile config_file;
227 create_ld_config_file(config_file.filename);
228 std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
Jiyong Park02586a22017-05-20 01:01:24 +0900229 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
Jiyong Park02586a22017-05-20 01:01:24 +0900238// 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.
241TEST(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 }
dimitry59d30622017-10-18 13:23:08 +0200248 if (is_debuggable_build()) {
Jiyong Park4945d8f2017-08-30 11:30:53 +0900249 // Skip the test for non production devices
250 return;
251 }
252
Jiyong Park02586a22017-05-20 01:01:24 +0900253 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";
Ryan Prichard0044cd12018-04-03 20:03:12 -0700256 TemporaryFile config_file;
257 create_ld_config_file(config_file.filename);
258 std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
Jiyong Park02586a22017-05-20 01:01:24 +0900259 chmod(helper.c_str(), 0755);
260 ExecTestHelper eth;
261 eth.SetArgs({ helper.c_str(), nullptr });
262 eth.SetEnv({ env.c_str(), nullptr });
Jiyong Park98283862017-11-28 13:37:03 +0900263 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, EXIT_FAILURE, error_message.c_str());
Jiyong Park02586a22017-05-20 01:01:24 +0900264#endif
265}