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
main_global_default_serial()36 extern "C" int main_global_default_serial() {
37 return 3370318;
38 }
39
main_global_protected_serial()40 extern "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
48 extern "C" int main_global_default_get_serial();
49
50 // This one calls main_global_protected_serial
51 extern "C" int main_global_protected_get_serial();
52
53 // This one calls lib_global_default_serial
54 extern "C" int lib_global_default_get_serial();
55
56 // This one calls lib_global_protected_serial
57 extern "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.
TEST(dl,main_preempts_global_default)62 TEST(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
TEST(dl,main_does_not_preempt_global_protected)68 TEST(dl, main_does_not_preempt_global_protected) {
69 ASSERT_EQ(3370318, main_global_protected_get_serial());
70 }
71
72 // check same things for lib
TEST(dl,lib_preempts_global_default)73 TEST(dl, lib_preempts_global_default) {
74 ASSERT_EQ(3370318, lib_global_default_get_serial());
75 }
76
TEST(dl,lib_does_not_preempt_global_protected)77 TEST(dl, lib_does_not_preempt_global_protected) {
78 ASSERT_EQ(3370318, lib_global_protected_get_serial());
79 }
80
TEST(dl,exec_linker)81 TEST(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
TEST(dl,preinit_system_calls)96 TEST(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
TEST(dl,xfail_preinit_getauxval)107 TEST(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
TEST(dl,exec_without_ld_preload)119 TEST(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
TEST(dl,exec_with_ld_preload)130 TEST(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.
TEST(dl,exec_without_ld_config_file)157 TEST(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__)
create_ld_config_file(std::string & config_file)170 static 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__)
is_user_build()184 static 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.
TEST(dl,exec_with_ld_config_file)195 TEST(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.
TEST(dl,exec_with_ld_config_file_with_ld_preload)217 TEST(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.
TEST(dl,disable_ld_config_file)240 TEST(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