Home | History | Annotate | Download | only in tests
      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 
     36 extern "C" int main_global_default_serial() {
     37   return 3370318;
     38 }
     39 
     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.
     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
     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
     73 TEST(dl, lib_preempts_global_default) {
     74   ASSERT_EQ(3370318, lib_global_default_get_serial());
     75 }
     76 
     77 TEST(dl, lib_does_not_preempt_global_protected) {
     78   ASSERT_EQ(3370318, lib_global_protected_get_serial());
     79 }
     80 
     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 
     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 
    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 
    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 
    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.
    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__)
    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__)
    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.
    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.
    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.
    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