• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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