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