blob: 38d77833213b793ac4036767790c4fd66379ebfc [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__)
Ryan Prichard0044cd12018-04-03 20:03:12 -0700171static void create_ld_config_file(const char* config_file) {
172 std::ofstream fout(config_file, std::ios::out);
Jiyong Park02586a22017-05-20 01:01:24 +0900173 fout << "dir.test = " << get_testlib_root() << "/ld_config_test_helper/" << std::endl
174 << "[test]" << std::endl
175 << "additional.namespaces = ns2" << std::endl
176 << "namespace.default.search.paths = " << get_testlib_root() << std::endl
177 << "namespace.default.links = ns2" << std::endl
178 << "namespace.default.link.ns2.shared_libs = libc.so:libm.so:libdl.so:ld_config_test_helper_lib1.so" << std::endl
179 << "namespace.ns2.search.paths = /system/${LIB}:" << get_testlib_root() << "/ns2" << std::endl;
180 fout.close();
181}
182#endif
183
Jiyong Park41704cd2017-09-19 09:48:07 +0900184#if defined(__BIONIC__)
dimitry59d30622017-10-18 13:23:08 +0200185static bool is_debuggable_build() {
186 return android::base::GetBoolProperty("ro.debuggable", false);
Jiyong Park41704cd2017-09-19 09:48:07 +0900187}
188#endif
Jiyong Park02586a22017-05-20 01:01:24 +0900189
190// _lib1.so and _lib2.so are now searchable by having another namespace 'ns2'
191// whose search paths include the 'ns2/' subdir.
192TEST(dl, exec_with_ld_config_file) {
193#if defined(__BIONIC__)
dimitry59d30622017-10-18 13:23:08 +0200194 if (!is_debuggable_build()) {
Jiyong Park41704cd2017-09-19 09:48:07 +0900195 // LD_CONFIG_FILE is not supported on user build
196 return;
197 }
Jiyong Park02586a22017-05-20 01:01:24 +0900198 std::string helper = get_testlib_root() +
199 "/ld_config_test_helper/ld_config_test_helper";
Ryan Prichard0044cd12018-04-03 20:03:12 -0700200 TemporaryFile config_file;
201 create_ld_config_file(config_file.filename);
202 std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
Jiyong Park02586a22017-05-20 01:01:24 +0900203 chmod(helper.c_str(), 0755);
204 ExecTestHelper eth;
205 eth.SetArgs({ helper.c_str(), nullptr });
206 eth.SetEnv({ env.c_str(), nullptr });
207 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "12345");
208#endif
209}
210
211// _lib3.so has same symbol as lib2.so but returns 54321. _lib3.so is
212// LD_PRELOADed. This test is to ensure LD_PRELOADed libs are available to
213// additional namespaces other than the default namespace.
214TEST(dl, exec_with_ld_config_file_with_ld_preload) {
215#if defined(__BIONIC__)
dimitry59d30622017-10-18 13:23:08 +0200216 if (!is_debuggable_build()) {
Jiyong Park41704cd2017-09-19 09:48:07 +0900217 // LD_CONFIG_FILE is not supported on user build
218 return;
219 }
Jiyong Park02586a22017-05-20 01:01:24 +0900220 std::string helper = get_testlib_root() +
221 "/ld_config_test_helper/ld_config_test_helper";
Ryan Prichard0044cd12018-04-03 20:03:12 -0700222 TemporaryFile config_file;
223 create_ld_config_file(config_file.filename);
224 std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
Jiyong Park02586a22017-05-20 01:01:24 +0900225 std::string env2 = std::string("LD_PRELOAD=") + get_testlib_root() + "/ld_config_test_helper_lib3.so";
226 chmod(helper.c_str(), 0755);
227 ExecTestHelper eth;
228 eth.SetArgs({ helper.c_str(), nullptr });
229 eth.SetEnv({ env.c_str(), env2.c_str(), nullptr });
230 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "54321");
231#endif
232}
233
Jiyong Park02586a22017-05-20 01:01:24 +0900234// ensures that LD_CONFIG_FILE env var does not work for production builds.
235// The test input is the same as exec_with_ld_config_file, but it must fail in
236// this case.
237TEST(dl, disable_ld_config_file) {
238#if defined(__BIONIC__)
239 if (getuid() == 0) {
240 // when executed from the shell (e.g. not as part of CTS), skip the test.
241 // This test is only for CTS.
242 return;
243 }
dimitry59d30622017-10-18 13:23:08 +0200244 if (is_debuggable_build()) {
Jiyong Park4945d8f2017-08-30 11:30:53 +0900245 // Skip the test for non production devices
246 return;
247 }
248
Jiyong Park02586a22017-05-20 01:01:24 +0900249 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";
250 std::string helper = get_testlib_root() +
251 "/ld_config_test_helper/ld_config_test_helper";
Ryan Prichard0044cd12018-04-03 20:03:12 -0700252 TemporaryFile config_file;
253 create_ld_config_file(config_file.filename);
254 std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
Jiyong Park02586a22017-05-20 01:01:24 +0900255 chmod(helper.c_str(), 0755);
256 ExecTestHelper eth;
257 eth.SetArgs({ helper.c_str(), nullptr });
258 eth.SetEnv({ env.c_str(), nullptr });
Jiyong Park98283862017-11-28 13:37:03 +0900259 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, EXIT_FAILURE, error_message.c_str());
Jiyong Park02586a22017-05-20 01:01:24 +0900260#endif
261}