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