OSDN Git Service

linker: the global group is added to all built-in namespaces
[android-x86/bionic.git] / tests / dl_test.cpp
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 #include <dlfcn.h>
20 #include <libgen.h>
21 #include <limits.h>
22 #include <stdio.h>
23 #include <stdint.h>
24
25 #include <string>
26 #include <iostream>
27 #include <fstream>
28
29 #include "gtest_globals.h"
30 #include "utils.h"
31
32 extern "C" int main_global_default_serial() {
33   return 3370318;
34 }
35
36 extern "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
44 extern "C" int main_global_default_get_serial();
45
46 // This one calls main_global_protected_serial
47 extern "C" int main_global_protected_get_serial();
48
49 // This one calls lib_global_default_serial
50 extern "C" int lib_global_default_get_serial();
51
52 // This one calls lib_global_protected_serial
53 extern "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.
58 TEST(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
64 TEST(dl, main_does_not_preempt_global_protected) {
65   ASSERT_EQ(3370318, main_global_protected_get_serial());
66 }
67
68 // check same things for lib
69 TEST(dl, lib_preempts_global_default) {
70   ASSERT_EQ(3370318, lib_global_default_get_serial());
71 }
72
73 TEST(dl, lib_does_not_preempt_global_protected) {
74   ASSERT_EQ(3370318, lib_global_protected_get_serial());
75 }
76
77 TEST(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
92 TEST(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
103 TEST(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
114
115 TEST(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
126 TEST(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.
153 TEST(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__)
166 static 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.
183 TEST(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.
201 TEST(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.
222 TEST(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 }