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