Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2014 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 <elf.h>
     21 #include <errno.h>
     22 #include <fcntl.h>
     23 #include <inttypes.h>
     24 #include <stdio.h>
     25 #include <string.h>
     26 #include <unistd.h>
     27 
     28 #include <android/dlext.h>
     29 #include <android-base/strings.h>
     30 
     31 #include <linux/memfd.h>
     32 #include <sys/mman.h>
     33 #include <sys/syscall.h>
     34 #include <sys/types.h>
     35 #include <sys/vfs.h>
     36 #include <sys/wait.h>
     37 
     38 #include <pagemap/pagemap.h>
     39 #include <ziparchive/zip_archive.h>
     40 
     41 #include "gtest_globals.h"
     42 #include "TemporaryFile.h"
     43 #include "utils.h"
     44 #include "dlext_private.h"
     45 #include "dlfcn_symlink_support.h"
     46 
     47 #define ASSERT_DL_NOTNULL(ptr) \
     48     ASSERT_TRUE((ptr) != nullptr) << "dlerror: " << dlerror()
     49 
     50 #define ASSERT_DL_ZERO(i) \
     51     ASSERT_EQ(0, i) << "dlerror: " << dlerror()
     52 
     53 #define ASSERT_NOERROR(i) \
     54     ASSERT_NE(-1, i) << "errno: " << strerror(errno)
     55 
     56 #define ASSERT_SUBSTR(needle, haystack) \
     57     ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
     58 
     59 
     60 typedef int (*fn)(void);
     61 constexpr const char* kLibName = "libdlext_test.so";
     62 constexpr const char* kLibNameNoRelro = "libdlext_test_norelro.so";
     63 constexpr const char* kLibZipSimpleZip = "libdir/libatest_simple_zip.so";
     64 constexpr auto kLibSize = 1024 * 1024; // how much address space to reserve for it
     65 
     66 class DlExtTest : public ::testing::Test {
     67 protected:
     68   virtual void SetUp() {
     69     handle_ = nullptr;
     70     // verify that we don't have the library loaded already
     71     void* h = dlopen(kLibName, RTLD_NOW | RTLD_NOLOAD);
     72     ASSERT_TRUE(h == nullptr);
     73     h = dlopen(kLibNameNoRelro, RTLD_NOW | RTLD_NOLOAD);
     74     ASSERT_TRUE(h == nullptr);
     75     // call dlerror() to swallow the error, and check it was the one we wanted
     76     ASSERT_EQ(std::string("dlopen failed: library \"") + kLibNameNoRelro + "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
     77   }
     78 
     79   virtual void TearDown() {
     80     if (handle_ != nullptr) {
     81       ASSERT_DL_ZERO(dlclose(handle_));
     82     }
     83   }
     84 
     85   void* handle_;
     86 };
     87 
     88 TEST_F(DlExtTest, ExtInfoNull) {
     89   handle_ = android_dlopen_ext(kLibName, RTLD_NOW, nullptr);
     90   ASSERT_DL_NOTNULL(handle_);
     91   fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
     92   ASSERT_DL_NOTNULL(f);
     93   EXPECT_EQ(4, f());
     94 }
     95 
     96 TEST_F(DlExtTest, ExtInfoNoFlags) {
     97   android_dlextinfo extinfo;
     98   extinfo.flags = 0;
     99   handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
    100   ASSERT_DL_NOTNULL(handle_);
    101   fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
    102   ASSERT_DL_NOTNULL(f);
    103   EXPECT_EQ(4, f());
    104 }
    105 
    106 TEST_F(DlExtTest, ExtInfoUseFd) {
    107   const std::string lib_path = get_testlib_root() + "/libdlext_test_fd/libdlext_test_fd.so";
    108 
    109   android_dlextinfo extinfo;
    110   extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD;
    111   extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
    112   ASSERT_TRUE(extinfo.library_fd != -1);
    113   handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
    114   ASSERT_DL_NOTNULL(handle_);
    115   fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
    116   ASSERT_DL_NOTNULL(f);
    117   EXPECT_EQ(4, f());
    118 
    119   uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
    120   ASSERT_DL_NOTNULL(taxicab_number);
    121   EXPECT_EQ(1729U, *taxicab_number);
    122 }
    123 
    124 TEST_F(DlExtTest, ExtInfoUseFdWithOffset) {
    125   const std::string lib_path = get_testlib_root() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
    126 
    127   android_dlextinfo extinfo;
    128   extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
    129   extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
    130 
    131   // Find the offset of the shared library in the zip.
    132   ZipArchiveHandle handle;
    133   ASSERT_EQ(0, OpenArchive(lib_path.c_str(), &handle));
    134   ZipEntry zip_entry;
    135   ZipString zip_name;
    136   zip_name.name = reinterpret_cast<const uint8_t*>(kLibZipSimpleZip);
    137   zip_name.name_length = strlen(kLibZipSimpleZip);
    138   ASSERT_EQ(0, FindEntry(handle, zip_name, &zip_entry));
    139   extinfo.library_fd_offset = zip_entry.offset;
    140   CloseArchive(handle);
    141 
    142   handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
    143   ASSERT_DL_NOTNULL(handle_);
    144 
    145   uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
    146   ASSERT_DL_NOTNULL(taxicab_number);
    147   EXPECT_EQ(1729U, *taxicab_number);
    148 }
    149 
    150 TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) {
    151   const std::string lib_path = get_testlib_root() + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
    152 
    153   android_dlextinfo extinfo;
    154   extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
    155   extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path.c_str(), O_RDONLY | O_CLOEXEC));
    156   extinfo.library_fd_offset = 17;
    157 
    158   handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
    159   ASSERT_TRUE(handle_ == nullptr);
    160   ASSERT_STREQ("dlopen failed: file offset for the library \"libname_placeholder\" is not page-aligned: 17", dlerror());
    161 
    162   // Test an address above 2^44, for http://b/18178121 .
    163   extinfo.library_fd_offset = (5LL<<48) + PAGE_SIZE;
    164   handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
    165   ASSERT_TRUE(handle_ == nullptr);
    166   ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" >= file size", dlerror());
    167 
    168   extinfo.library_fd_offset = 0LL - PAGE_SIZE;
    169   handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
    170   ASSERT_TRUE(handle_ == nullptr);
    171   ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" is negative", dlerror());
    172 
    173   extinfo.library_fd_offset = 0;
    174   handle_ = android_dlopen_ext("libname_ignored", RTLD_NOW, &extinfo);
    175   ASSERT_TRUE(handle_ == nullptr);
    176   ASSERT_EQ("dlopen failed: \"" + lib_path + "\" has bad ELF magic", dlerror());
    177 
    178   // Check if dlsym works after unsuccessful dlopen().
    179   // Supply non-exiting one to make linker visit every soinfo.
    180   void* sym = dlsym(RTLD_DEFAULT, "this_symbol_does_not_exist___");
    181   ASSERT_TRUE(sym == nullptr);
    182 
    183   close(extinfo.library_fd);
    184 }
    185 
    186 TEST_F(DlExtTest, ExtInfoUseOffsetWithoutFd) {
    187   android_dlextinfo extinfo;
    188   extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
    189   // This offset will not be used, so it doesn't matter.
    190   extinfo.library_fd_offset = 0;
    191 
    192   handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo);
    193   ASSERT_TRUE(handle_ == nullptr);
    194   ASSERT_STREQ("dlopen failed: invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x20", dlerror());
    195 }
    196 
    197 TEST(dlext, android_dlopen_ext_force_load_smoke) {
    198   DlfcnSymlink symlink("android_dlopen_ext_force_load_smoke");
    199   const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
    200   // 1. Open actual file
    201   void* handle = dlopen("libdlext_test.so", RTLD_NOW);
    202   ASSERT_DL_NOTNULL(handle);
    203   // 2. Open link with force_load flag set
    204   android_dlextinfo extinfo;
    205   extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
    206   void* handle2 = android_dlopen_ext(symlink_name.c_str(), RTLD_NOW, &extinfo);
    207   ASSERT_DL_NOTNULL(handle2);
    208   ASSERT_TRUE(handle != handle2);
    209 
    210   dlclose(handle2);
    211   dlclose(handle);
    212 }
    213 
    214 TEST(dlext, android_dlopen_ext_force_load_soname_exception) {
    215   DlfcnSymlink symlink("android_dlopen_ext_force_load_soname_exception");
    216   const std::string symlink_name = basename(symlink.get_symlink_path().c_str());
    217   // Check if soname lookup still returns already loaded library
    218   // when ANDROID_DLEXT_FORCE_LOAD flag is specified.
    219   void* handle = dlopen(symlink_name.c_str(), RTLD_NOW);
    220   ASSERT_DL_NOTNULL(handle);
    221 
    222   android_dlextinfo extinfo;
    223   extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
    224 
    225   // Note that 'libdlext_test.so' is dt_soname for the symlink_name
    226   void* handle2 = android_dlopen_ext("libdlext_test.so", RTLD_NOW, &extinfo);
    227 
    228   ASSERT_DL_NOTNULL(handle2);
    229   ASSERT_TRUE(handle == handle2);
    230 
    231   dlclose(handle2);
    232   dlclose(handle);
    233 }
    234 
    235 TEST(dlfcn, dlopen_from_zip_absolute_path) {
    236   const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
    237   const std::string lib_path = get_testlib_root() + lib_zip_path;
    238 
    239   void* handle = dlopen((lib_path + "!/libdir/libatest_simple_zip.so").c_str(), RTLD_NOW);
    240   ASSERT_TRUE(handle != nullptr) << dlerror();
    241 
    242   uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
    243   ASSERT_DL_NOTNULL(taxicab_number);
    244   EXPECT_EQ(1729U, *taxicab_number);
    245 
    246   dlclose(handle);
    247 }
    248 
    249 TEST(dlfcn, dlopen_from_zip_with_dt_runpath) {
    250   const std::string lib_zip_path = "/libdlext_test_runpath_zip/libdlext_test_runpath_zip_zipaligned.zip";
    251   const std::string lib_path = get_testlib_root() + lib_zip_path;
    252 
    253   void* handle = dlopen((lib_path + "!/libdir/libtest_dt_runpath_d_zip.so").c_str(), RTLD_NOW);
    254 
    255   ASSERT_TRUE(handle != nullptr) << dlerror();
    256 
    257   typedef void *(* dlopen_b_fn)();
    258   dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
    259   ASSERT_TRUE(fn != nullptr) << dlerror();
    260 
    261   void *p = fn();
    262   ASSERT_TRUE(p != nullptr) << dlerror();
    263 
    264   dlclose(p);
    265   dlclose(handle);
    266 }
    267 
    268 TEST(dlfcn, dlopen_from_zip_ld_library_path) {
    269   const std::string lib_zip_path = "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip";
    270   const std::string lib_path = get_testlib_root() + lib_zip_path + "!/libdir";
    271 
    272   typedef void (*fn_t)(const char*);
    273   fn_t android_update_LD_LIBRARY_PATH =
    274       reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH"));
    275 
    276   ASSERT_TRUE(android_update_LD_LIBRARY_PATH != nullptr) << dlerror();
    277 
    278   void* handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
    279   ASSERT_TRUE(handle == nullptr);
    280 
    281   android_update_LD_LIBRARY_PATH(lib_path.c_str());
    282 
    283   handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
    284   ASSERT_TRUE(handle != nullptr) << dlerror();
    285 
    286   int (*fn)(void);
    287   fn = reinterpret_cast<int (*)(void)>(dlsym(handle, "getRandomNumber"));
    288   ASSERT_TRUE(fn != nullptr);
    289   EXPECT_EQ(4, fn());
    290 
    291   uint32_t* taxicab_number =
    292           reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
    293   ASSERT_DL_NOTNULL(taxicab_number);
    294   EXPECT_EQ(1729U, *taxicab_number);
    295 
    296   dlclose(handle);
    297 }
    298 
    299 
    300 TEST_F(DlExtTest, Reserved) {
    301   void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    302   ASSERT_TRUE(start != MAP_FAILED);
    303   android_dlextinfo extinfo;
    304   extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
    305   extinfo.reserved_addr = start;
    306   extinfo.reserved_size = kLibSize;
    307   handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
    308   ASSERT_DL_NOTNULL(handle_);
    309   fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
    310   ASSERT_DL_NOTNULL(f);
    311   EXPECT_GE(reinterpret_cast<void*>(f), start);
    312   EXPECT_LT(reinterpret_cast<void*>(f),
    313             reinterpret_cast<char*>(start) + kLibSize);
    314   EXPECT_EQ(4, f());
    315 
    316   // Check that after dlclose reserved address space is unmapped (and can be reused)
    317   dlclose(handle_);
    318   handle_ = nullptr;
    319 
    320   void* new_start = mmap(start, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    321   ASSERT_NE(start, new_start) << "dlclose unmapped reserved space";
    322 }
    323 
    324 TEST_F(DlExtTest, ReservedTooSmall) {
    325   void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    326   ASSERT_TRUE(start != MAP_FAILED);
    327   android_dlextinfo extinfo;
    328   extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
    329   extinfo.reserved_addr = start;
    330   extinfo.reserved_size = PAGE_SIZE;
    331   handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
    332   EXPECT_EQ(nullptr, handle_);
    333 }
    334 
    335 TEST_F(DlExtTest, ReservedHint) {
    336   void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    337   ASSERT_TRUE(start != MAP_FAILED);
    338   android_dlextinfo extinfo;
    339   extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
    340   extinfo.reserved_addr = start;
    341   extinfo.reserved_size = kLibSize;
    342   handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
    343   ASSERT_DL_NOTNULL(handle_);
    344   fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
    345   ASSERT_DL_NOTNULL(f);
    346   EXPECT_GE(reinterpret_cast<void*>(f), start);
    347   EXPECT_LT(reinterpret_cast<void*>(f),
    348             reinterpret_cast<char*>(start) + kLibSize);
    349   EXPECT_EQ(4, f());
    350 }
    351 
    352 TEST_F(DlExtTest, ReservedHintTooSmall) {
    353   void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    354   ASSERT_TRUE(start != MAP_FAILED);
    355   android_dlextinfo extinfo;
    356   extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
    357   extinfo.reserved_addr = start;
    358   extinfo.reserved_size = PAGE_SIZE;
    359   handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
    360   ASSERT_DL_NOTNULL(handle_);
    361   fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
    362   ASSERT_DL_NOTNULL(f);
    363   EXPECT_TRUE(reinterpret_cast<void*>(f) < start ||
    364               (reinterpret_cast<void*>(f) >=
    365                reinterpret_cast<char*>(start) + PAGE_SIZE));
    366   EXPECT_EQ(4, f());
    367 }
    368 
    369 TEST_F(DlExtTest, LoadAtFixedAddress) {
    370   void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    371   ASSERT_TRUE(start != MAP_FAILED);
    372   munmap(start, kLibSize);
    373 
    374   android_dlextinfo extinfo;
    375   extinfo.flags = ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;
    376   extinfo.reserved_addr = start;
    377 
    378   handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
    379   ASSERT_DL_NOTNULL(handle_);
    380   fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
    381   ASSERT_DL_NOTNULL(f);
    382   EXPECT_GE(reinterpret_cast<void*>(f), start);
    383   EXPECT_LT(reinterpret_cast<void*>(f), reinterpret_cast<char*>(start) + kLibSize);
    384 
    385   EXPECT_EQ(4, f());
    386   dlclose(handle_);
    387   handle_ = nullptr;
    388 
    389   // Check that dlclose unmapped the file
    390   void* addr = mmap(start, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    391   ASSERT_EQ(start, addr) << "dlclose did not unmap the memory";
    392 }
    393 
    394 TEST_F(DlExtTest, LoadAtFixedAddressTooSmall) {
    395   void* start = mmap(nullptr, kLibSize + PAGE_SIZE, PROT_NONE,
    396                          MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    397   ASSERT_TRUE(start != MAP_FAILED);
    398   munmap(start, kLibSize + PAGE_SIZE);
    399   void* new_addr = mmap(reinterpret_cast<uint8_t*>(start) + PAGE_SIZE, kLibSize, PROT_NONE,
    400                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    401   ASSERT_TRUE(new_addr != MAP_FAILED);
    402 
    403   android_dlextinfo extinfo;
    404   extinfo.flags = ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;
    405   extinfo.reserved_addr = start;
    406 
    407   handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
    408   ASSERT_TRUE(handle_ == nullptr);
    409 }
    410 
    411 class DlExtRelroSharingTest : public DlExtTest {
    412 protected:
    413   virtual void SetUp() {
    414     DlExtTest::SetUp();
    415     void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    416     ASSERT_TRUE(start != MAP_FAILED);
    417     extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
    418     extinfo_.reserved_addr = start;
    419     extinfo_.reserved_size = kLibSize;
    420     extinfo_.relro_fd = -1;
    421   }
    422 
    423   virtual void TearDown() {
    424     DlExtTest::TearDown();
    425   }
    426 
    427   void CreateRelroFile(const char* lib, const char* relro_file) {
    428     int relro_fd = open(relro_file, O_RDWR | O_TRUNC);
    429     ASSERT_NOERROR(relro_fd);
    430 
    431     pid_t pid = fork();
    432     if (pid == 0) {
    433       // child process
    434       extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
    435       extinfo_.relro_fd = relro_fd;
    436       void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
    437       if (handle == nullptr) {
    438         fprintf(stderr, "in child: %s\n", dlerror());
    439         exit(1);
    440       }
    441       exit(0);
    442     }
    443 
    444     // continuing in parent
    445     ASSERT_NOERROR(close(relro_fd));
    446     ASSERT_NOERROR(pid);
    447     AssertChildExited(pid, 0);
    448 
    449     // reopen file for reading so it can be used
    450     relro_fd = open(relro_file, O_RDONLY);
    451     ASSERT_NOERROR(relro_fd);
    452     extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
    453     extinfo_.relro_fd = relro_fd;
    454   }
    455 
    456   void TryUsingRelro(const char* lib) {
    457     handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
    458     ASSERT_DL_NOTNULL(handle_);
    459     fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
    460     ASSERT_DL_NOTNULL(f);
    461     EXPECT_EQ(4, f());
    462 
    463     uint32_t* taxicab_number =
    464             reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
    465     ASSERT_DL_NOTNULL(taxicab_number);
    466     EXPECT_EQ(1729U, *taxicab_number);
    467   }
    468 
    469   void SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file, bool share_relro,
    470                                   size_t* pss_out);
    471 
    472   android_dlextinfo extinfo_;
    473 };
    474 
    475 TEST_F(DlExtRelroSharingTest, ChildWritesGoodData) {
    476   TemporaryFile tf; // Use tf to get an unique filename.
    477   ASSERT_NOERROR(close(tf.fd));
    478 
    479   ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.filename));
    480   ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName));
    481 
    482   // Use destructor of tf to close and unlink the file.
    483   tf.fd = extinfo_.relro_fd;
    484 }
    485 
    486 TEST_F(DlExtRelroSharingTest, ChildWritesNoRelro) {
    487   TemporaryFile tf; // // Use tf to get an unique filename.
    488   ASSERT_NOERROR(close(tf.fd));
    489 
    490   ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.filename));
    491   ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro));
    492 
    493   // Use destructor of tf to close and unlink the file.
    494   tf.fd = extinfo_.relro_fd;
    495 }
    496 
    497 TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
    498   ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName));
    499 }
    500 
    501 TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
    502   if (geteuid() != 0) {
    503     GTEST_LOG_(INFO) << "This test must be run as root.\n";
    504     return;
    505   }
    506 
    507   TemporaryFile tf; // Use tf to get an unique filename.
    508   ASSERT_NOERROR(close(tf.fd));
    509 
    510   ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.filename));
    511 
    512   int pipefd[2];
    513   ASSERT_NOERROR(pipe(pipefd));
    514 
    515   size_t without_sharing, with_sharing;
    516   ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.filename, false, &without_sharing));
    517   ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.filename, true, &with_sharing));
    518   ASSERT_LT(with_sharing, without_sharing);
    519 
    520   // We expect the sharing to save at least 50% of the library's total PSS.
    521   // In practice it saves 80%+ for this library in the test.
    522   size_t pss_saved = without_sharing - with_sharing;
    523   size_t expected_min_saved = without_sharing / 2;
    524 
    525   EXPECT_LT(expected_min_saved, pss_saved);
    526 
    527   // Use destructor of tf to close and unlink the file.
    528   tf.fd = extinfo_.relro_fd;
    529 }
    530 
    531 void GetPss(bool shared_relro, const char* lib, const char* relro_file, pid_t pid,
    532             size_t* total_pss) {
    533   pm_kernel_t* kernel;
    534   ASSERT_EQ(0, pm_kernel_create(&kernel));
    535 
    536   pm_process_t* process;
    537   ASSERT_EQ(0, pm_process_create(kernel, pid, &process));
    538 
    539   pm_map_t** maps;
    540   size_t num_maps;
    541   ASSERT_EQ(0, pm_process_maps(process, &maps, &num_maps));
    542 
    543   // Calculate total PSS of the library.
    544   *total_pss = 0;
    545   bool saw_relro_file = false;
    546   for (size_t i = 0; i < num_maps; ++i) {
    547     if (android::base::EndsWith(maps[i]->name, lib) || strcmp(maps[i]->name, relro_file) == 0) {
    548       if (strcmp(maps[i]->name, relro_file) == 0) saw_relro_file = true;
    549 
    550       pm_memusage_t usage;
    551       ASSERT_EQ(0, pm_map_usage(maps[i], &usage));
    552       *total_pss += usage.pss;
    553     }
    554   }
    555 
    556   free(maps);
    557   pm_process_destroy(process);
    558   pm_kernel_destroy(kernel);
    559 
    560   if (shared_relro) ASSERT_TRUE(saw_relro_file);
    561 }
    562 
    563 void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file,
    564                                                        bool share_relro, size_t* pss_out) {
    565   const int CHILDREN = 20;
    566 
    567   // Create children
    568   pid_t child_pids[CHILDREN];
    569   int childpipe[CHILDREN];
    570   for (int i=0; i<CHILDREN; ++i) {
    571     char read_buf;
    572     int child_done_pipe[2], parent_done_pipe[2];
    573     ASSERT_NOERROR(pipe(child_done_pipe));
    574     ASSERT_NOERROR(pipe(parent_done_pipe));
    575 
    576     pid_t child = fork();
    577     if (child == 0) {
    578       // close the 'wrong' ends of the pipes in the child
    579       close(child_done_pipe[0]);
    580       close(parent_done_pipe[1]);
    581 
    582       // open the library
    583       void* handle;
    584       if (share_relro) {
    585         handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
    586       } else {
    587         handle = dlopen(lib, RTLD_NOW);
    588       }
    589       if (handle == nullptr) {
    590         fprintf(stderr, "in child: %s\n", dlerror());
    591         exit(1);
    592       }
    593 
    594       // close write end of child_done_pipe to signal the parent that we're done.
    595       close(child_done_pipe[1]);
    596 
    597       // wait for the parent to close parent_done_pipe, then exit
    598       read(parent_done_pipe[0], &read_buf, 1);
    599       exit(0);
    600     }
    601 
    602     ASSERT_NOERROR(child);
    603 
    604     // close the 'wrong' ends of the pipes in the parent
    605     close(child_done_pipe[1]);
    606     close(parent_done_pipe[0]);
    607 
    608     // wait for the child to be done
    609     read(child_done_pipe[0], &read_buf, 1);
    610     close(child_done_pipe[0]);
    611 
    612     // save the child's pid and the parent_done_pipe
    613     child_pids[i] = child;
    614     childpipe[i] = parent_done_pipe[1];
    615   }
    616 
    617   // Sum the PSS of tested library of all the children
    618   size_t total_pss = 0;
    619   for (int i=0; i<CHILDREN; ++i) {
    620     size_t child_pss;
    621     ASSERT_NO_FATAL_FAILURE(GetPss(share_relro, lib, relro_file, child_pids[i], &child_pss));
    622     total_pss += child_pss;
    623   }
    624   *pss_out = total_pss;
    625 
    626   // Close pipes and wait for children to exit
    627   for (int i=0; i<CHILDREN; ++i) {
    628     ASSERT_NOERROR(close(childpipe[i]));
    629   }
    630   for (int i = 0; i < CHILDREN; ++i) {
    631     AssertChildExited(child_pids[i], 0);
    632   }
    633 }
    634 
    635 // Testing namespaces
    636 static const char* g_public_lib = "libnstest_public.so";
    637 
    638 // These are libs shared with default namespace
    639 static const std::string g_core_shared_libs = "libc.so:libc++.so:libdl.so:libm.so";
    640 
    641 TEST(dlext, ns_smoke) {
    642   static const char* root_lib = "libnstest_root.so";
    643   std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
    644 
    645   ASSERT_FALSE(android_init_anonymous_namespace("", nullptr));
    646   ASSERT_STREQ("android_init_anonymous_namespace failed: error linking namespaces"
    647                " \"(anonymous)\"->\"(default)\": the list of shared libraries is empty.",
    648                dlerror());
    649 
    650   const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib;
    651   void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
    652   ASSERT_TRUE(handle_public != nullptr) << dlerror();
    653 
    654   ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
    655 
    656   // Check that libraries added to public namespace are not NODELETE
    657   dlclose(handle_public);
    658   handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
    659   ASSERT_TRUE(handle_public == nullptr);
    660   ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
    661                "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
    662 
    663   handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
    664 
    665   // create "public namespace", share limited set of public libraries with
    666 
    667   android_namespace_t* ns1 =
    668           android_create_namespace("private",
    669                                    nullptr,
    670                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
    671                                    ANDROID_NAMESPACE_TYPE_REGULAR,
    672                                    nullptr,
    673                                    nullptr);
    674   ASSERT_TRUE(ns1 != nullptr) << dlerror();
    675   ASSERT_TRUE(android_link_namespaces(ns1, nullptr, shared_libs.c_str())) << dlerror();
    676 
    677   android_namespace_t* ns2 =
    678           android_create_namespace("private_isolated",
    679                                    nullptr,
    680                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
    681                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
    682                                    nullptr,
    683                                    nullptr);
    684   ASSERT_TRUE(ns2 != nullptr) << dlerror();
    685   ASSERT_TRUE(android_link_namespaces(ns2, nullptr, shared_libs.c_str())) << dlerror();
    686 
    687   // This should not have affect search path for default namespace:
    688   ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
    689   void* handle = dlopen(g_public_lib, RTLD_NOW);
    690   ASSERT_TRUE(handle != nullptr) << dlerror();
    691   dlclose(handle);
    692 
    693   // dlopen for a public library using an absolute path should work
    694   // 1. For isolated namespaces
    695   android_dlextinfo extinfo;
    696   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
    697   extinfo.library_namespace = ns2;
    698   handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
    699   ASSERT_TRUE(handle != nullptr) << dlerror();
    700   ASSERT_TRUE(handle == handle_public);
    701 
    702   dlclose(handle);
    703 
    704   // 1.1 even if it wasn't loaded before
    705   dlclose(handle_public);
    706 
    707   handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
    708   ASSERT_TRUE(handle_public == nullptr);
    709   ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
    710                "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
    711 
    712   handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
    713   ASSERT_TRUE(handle != nullptr) << dlerror();
    714 
    715   handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
    716   ASSERT_TRUE(handle == handle_public);
    717 
    718   dlclose(handle);
    719 
    720   // 2. And for regular namespaces (make sure it does not load second copy of the library)
    721   extinfo.library_namespace = ns1;
    722   handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
    723   ASSERT_TRUE(handle != nullptr) << dlerror();
    724   ASSERT_TRUE(handle == handle_public);
    725 
    726   dlclose(handle);
    727 
    728   // 2.1 Unless it was not loaded before - in which case it will load a duplicate.
    729   // TODO(dimitry): This is broken. Maybe we need to deprecate non-isolated namespaces?
    730   dlclose(handle_public);
    731 
    732   handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW | RTLD_NOLOAD);
    733   ASSERT_TRUE(handle_public == nullptr);
    734   ASSERT_EQ(std::string("dlopen failed: library \"") + lib_public_path +
    735                "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
    736 
    737   handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
    738   ASSERT_TRUE(handle != nullptr) << dlerror();
    739 
    740   handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
    741 
    742   ASSERT_TRUE(handle != handle_public);
    743 
    744   dlclose(handle);
    745 
    746   extinfo.library_namespace = ns1;
    747 
    748   void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
    749   ASSERT_TRUE(handle1 != nullptr) << dlerror();
    750 
    751   extinfo.library_namespace = ns2;
    752   void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
    753   ASSERT_TRUE(handle2 != nullptr) << dlerror();
    754 
    755   ASSERT_TRUE(handle1 != handle2);
    756 
    757   typedef const char* (*fn_t)();
    758 
    759   fn_t ns_get_local_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
    760   ASSERT_TRUE(ns_get_local_string1 != nullptr) << dlerror();
    761   fn_t ns_get_local_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
    762   ASSERT_TRUE(ns_get_local_string2 != nullptr) << dlerror();
    763 
    764   EXPECT_STREQ("This string is local to root library", ns_get_local_string1());
    765   EXPECT_STREQ("This string is local to root library", ns_get_local_string2());
    766 
    767   ASSERT_TRUE(ns_get_local_string1() != ns_get_local_string2());
    768 
    769   fn_t ns_get_private_extern_string1 =
    770           reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
    771   ASSERT_TRUE(ns_get_private_extern_string1 != nullptr) << dlerror();
    772   fn_t ns_get_private_extern_string2 =
    773           reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
    774   ASSERT_TRUE(ns_get_private_extern_string2 != nullptr) << dlerror();
    775 
    776   EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string1());
    777   EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
    778 
    779   ASSERT_TRUE(ns_get_private_extern_string1() != ns_get_private_extern_string2());
    780 
    781   fn_t ns_get_public_extern_string1 =
    782           reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
    783   ASSERT_TRUE(ns_get_public_extern_string1 != nullptr) << dlerror();
    784   fn_t ns_get_public_extern_string2 =
    785           reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
    786   ASSERT_TRUE(ns_get_public_extern_string2 != nullptr) << dlerror();
    787 
    788   EXPECT_STREQ("This string is from public namespace", ns_get_public_extern_string1());
    789   ASSERT_TRUE(ns_get_public_extern_string1() == ns_get_public_extern_string2());
    790 
    791   // and now check that dlopen() does the right thing in terms of preserving namespace
    792   fn_t ns_get_dlopened_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
    793   ASSERT_TRUE(ns_get_dlopened_string1 != nullptr) << dlerror();
    794   fn_t ns_get_dlopened_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
    795   ASSERT_TRUE(ns_get_dlopened_string2 != nullptr) << dlerror();
    796 
    797   EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string1());
    798   EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
    799 
    800   ASSERT_TRUE(ns_get_dlopened_string1() != ns_get_dlopened_string2());
    801 
    802   // Check that symbols from non-shared libraries a shared library depends on are not visible
    803   // from original namespace.
    804 
    805   fn_t ns_get_internal_extern_string =
    806           reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_internal_extern_string"));
    807   ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
    808   ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
    809       "ns_get_internal_extern_string() expected to return null but returns \"" <<
    810       ns_get_internal_extern_string() << "\"";
    811 
    812   dlclose(handle1);
    813 
    814   // Check if handle2 is still alive (and well)
    815   ASSERT_STREQ("This string is local to root library", ns_get_local_string2());
    816   ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
    817   ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string2());
    818   ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
    819 
    820   dlclose(handle2);
    821 }
    822 
    823 TEST(dlext, dlopen_ext_use_o_tmpfile_fd) {
    824   const std::string lib_path = get_testlib_root() + "/libtest_simple.so";
    825 
    826   int tmpfd = TEMP_FAILURE_RETRY(
    827         open(get_testlib_root().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL));
    828 
    829   // Ignore kernels without O_TMPFILE flag support
    830   if (tmpfd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) {
    831     return;
    832   }
    833 
    834   ASSERT_TRUE(tmpfd != -1) << strerror(errno);
    835 
    836   android_namespace_t* ns =
    837           android_create_namespace("testing-o_tmpfile",
    838                                    nullptr,
    839                                    get_testlib_root().c_str(),
    840                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
    841                                    nullptr,
    842                                    nullptr);
    843 
    844   ASSERT_DL_NOTNULL(ns);
    845 
    846   ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
    847 
    848   std::string content;
    849   ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
    850   ASSERT_TRUE(android::base::WriteStringToFd(content, tmpfd)) << strerror(errno);
    851 
    852   android_dlextinfo extinfo;
    853   extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
    854   extinfo.library_fd = tmpfd;
    855   extinfo.library_namespace = ns;
    856 
    857   void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
    858 
    859   ASSERT_DL_NOTNULL(handle);
    860 
    861   uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
    862   ASSERT_DL_NOTNULL(taxicab_number);
    863   EXPECT_EQ(1729U, *taxicab_number);
    864   dlclose(handle);
    865 }
    866 
    867 TEST(dlext, dlopen_ext_use_memfd) {
    868   const std::string lib_path = get_testlib_root() + "/libtest_simple.so";
    869 
    870   // create memfd
    871   int memfd = syscall(__NR_memfd_create, "foobar", MFD_CLOEXEC);
    872   if (memfd == -1 && errno == ENOSYS) {
    873     return;
    874   }
    875 
    876   ASSERT_TRUE(memfd != -1) << strerror(errno);
    877 
    878   // Check st.f_type is TMPFS_MAGIC for memfd
    879   struct statfs st;
    880   ASSERT_TRUE(TEMP_FAILURE_RETRY(fstatfs(memfd, &st)) == 0) << strerror(errno);
    881   ASSERT_EQ(static_cast<decltype(st.f_type)>(TMPFS_MAGIC), st.f_type);
    882 
    883   android_namespace_t* ns =
    884           android_create_namespace("testing-memfd",
    885                                    nullptr,
    886                                    get_testlib_root().c_str(),
    887                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
    888                                    nullptr,
    889                                    nullptr);
    890 
    891   ASSERT_DL_NOTNULL(ns);
    892 
    893   ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
    894 
    895   // read file into memfd backed one.
    896   std::string content;
    897   ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
    898   ASSERT_TRUE(android::base::WriteStringToFd(content, memfd)) << strerror(errno);
    899 
    900   android_dlextinfo extinfo;
    901   extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
    902   extinfo.library_fd = memfd;
    903   extinfo.library_namespace = ns;
    904 
    905   void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
    906 
    907   ASSERT_DL_NOTNULL(handle);
    908 
    909   uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
    910   ASSERT_DL_NOTNULL(taxicab_number);
    911   EXPECT_EQ(1729U, *taxicab_number);
    912   dlclose(handle);
    913 }
    914 
    915 TEST(dlext, ns_symbol_visibilty_one_namespace) {
    916   static const char* root_lib = "libnstest_root.so";
    917   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
    918 
    919   const std::string ns_search_path = get_testlib_root() + "/public_namespace_libs:" +
    920                                      get_testlib_root() + "/private_namespace_libs";
    921 
    922   android_namespace_t* ns =
    923           android_create_namespace("one",
    924                                    nullptr,
    925                                    ns_search_path.c_str(),
    926                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
    927                                    nullptr,
    928                                    nullptr);
    929 
    930   ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
    931 
    932   android_dlextinfo extinfo;
    933   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
    934   extinfo.library_namespace = ns;
    935 
    936   void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
    937   ASSERT_TRUE(handle != nullptr) << dlerror();
    938 
    939   typedef const char* (*fn_t)();
    940 
    941   // Check that relocation worked correctly
    942   fn_t ns_get_internal_extern_string =
    943           reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
    944   ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
    945   ASSERT_STREQ("This string is from a library a shared library depends on", ns_get_internal_extern_string());
    946 
    947   fn_t internal_extern_string_fn =
    948           reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
    949   ASSERT_TRUE(internal_extern_string_fn != nullptr) << dlerror();
    950   ASSERT_STREQ("This string is from a library a shared library depends on", internal_extern_string_fn());
    951 }
    952 
    953 TEST(dlext, ns_symbol_visibilty_between_namespaces) {
    954   static const char* root_lib = "libnstest_root.so";
    955   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
    956 
    957   const std::string public_ns_search_path =  get_testlib_root() + "/public_namespace_libs";
    958   const std::string private_ns_search_path = get_testlib_root() + "/private_namespace_libs";
    959 
    960   android_namespace_t* ns_public =
    961           android_create_namespace("public",
    962                                    nullptr,
    963                                    public_ns_search_path.c_str(),
    964                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
    965                                    nullptr,
    966                                    nullptr);
    967 
    968   ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
    969 
    970   android_namespace_t* ns_private =
    971           android_create_namespace("private",
    972                                    nullptr,
    973                                    private_ns_search_path.c_str(),
    974                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
    975                                    nullptr,
    976                                    nullptr);
    977 
    978   ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
    979   ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
    980 
    981   android_dlextinfo extinfo;
    982   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
    983   extinfo.library_namespace = ns_private;
    984 
    985   void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
    986   ASSERT_TRUE(handle != nullptr) << dlerror();
    987 
    988   typedef const char* (*fn_t)();
    989 
    990   // Check that relocation worked correctly
    991   fn_t ns_get_internal_extern_string =
    992           reinterpret_cast<fn_t>(dlsym(handle, "ns_get_internal_extern_string"));
    993   ASSERT_TRUE(ns_get_internal_extern_string != nullptr) << dlerror();
    994   ASSERT_TRUE(ns_get_internal_extern_string() == nullptr) <<
    995       "ns_get_internal_extern_string() expected to return null but returns \"" <<
    996       ns_get_internal_extern_string() << "\"";
    997 
    998   fn_t internal_extern_string_fn =
    999           reinterpret_cast<fn_t>(dlsym(handle, "internal_extern_string"));
   1000   ASSERT_TRUE(internal_extern_string_fn == nullptr);
   1001   ASSERT_STREQ("undefined symbol: internal_extern_string", dlerror());
   1002 }
   1003 
   1004 TEST(dlext, ns_unload_between_namespaces) {
   1005   static const char* root_lib = "libnstest_root.so";
   1006   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
   1007 
   1008   const std::string public_ns_search_path =  get_testlib_root() + "/public_namespace_libs";
   1009   const std::string private_ns_search_path = get_testlib_root() + "/private_namespace_libs";
   1010 
   1011   android_namespace_t* ns_public =
   1012           android_create_namespace("public",
   1013                                    nullptr,
   1014                                    public_ns_search_path.c_str(),
   1015                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
   1016                                    nullptr,
   1017                                    nullptr);
   1018 
   1019   ASSERT_TRUE(android_link_namespaces(ns_public, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1020 
   1021   android_namespace_t* ns_private =
   1022           android_create_namespace("private",
   1023                                    nullptr,
   1024                                    private_ns_search_path.c_str(),
   1025                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
   1026                                    nullptr,
   1027                                    nullptr);
   1028 
   1029   ASSERT_TRUE(android_link_namespaces(ns_private, ns_public, g_public_lib)) << dlerror();
   1030   ASSERT_TRUE(android_link_namespaces(ns_private, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1031 
   1032   android_dlextinfo extinfo;
   1033   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1034   extinfo.library_namespace = ns_private;
   1035 
   1036   void* handle = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
   1037   ASSERT_TRUE(handle != nullptr) << dlerror();
   1038 
   1039   dlclose(handle);
   1040   // Check that root_lib was unloaded
   1041   handle = android_dlopen_ext(root_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
   1042   ASSERT_TRUE(handle == nullptr);
   1043   ASSERT_EQ(std::string("dlopen failed: library \"") + root_lib +
   1044             "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
   1045 
   1046   // Check that shared library was unloaded in public ns
   1047   extinfo.library_namespace = ns_public;
   1048   handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
   1049   ASSERT_TRUE(handle == nullptr);
   1050   ASSERT_EQ(std::string("dlopen failed: library \"") + g_public_lib +
   1051             "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
   1052 }
   1053 
   1054 TEST(dlext, ns_greylist_enabled) {
   1055   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
   1056 
   1057   const std::string ns_search_path = get_testlib_root() + "/private_namespace_libs";
   1058 
   1059   android_namespace_t* ns =
   1060           android_create_namespace("namespace",
   1061                                    nullptr,
   1062                                    ns_search_path.c_str(),
   1063                                    ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED,
   1064                                    nullptr,
   1065                                    nullptr);
   1066 
   1067   ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1068 
   1069   android_dlextinfo extinfo;
   1070   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1071   extinfo.library_namespace = ns;
   1072 
   1073   // An app targeting M can open libnativehelper.so because it's on the greylist.
   1074   android_set_application_target_sdk_version(__ANDROID_API_M__);
   1075   void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
   1076   ASSERT_TRUE(handle != nullptr) << dlerror();
   1077 
   1078   // Check that loader did not load another copy of libdl.so while loading greylisted library.
   1079   void* dlsym_ptr = dlsym(handle, "dlsym");
   1080   ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror();
   1081   ASSERT_EQ(&dlsym, dlsym_ptr);
   1082 
   1083   dlclose(handle);
   1084 
   1085   // An app targeting N no longer has the greylist.
   1086   android_set_application_target_sdk_version(__ANDROID_API_N__);
   1087   handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
   1088   ASSERT_TRUE(handle == nullptr);
   1089   ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
   1090 }
   1091 
   1092 TEST(dlext, ns_greylist_disabled_by_default) {
   1093   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
   1094 
   1095   const std::string ns_search_path = get_testlib_root() + "/private_namespace_libs";
   1096 
   1097   android_namespace_t* ns =
   1098           android_create_namespace("namespace",
   1099                                    nullptr,
   1100                                    ns_search_path.c_str(),
   1101                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
   1102                                    nullptr,
   1103                                    nullptr);
   1104 
   1105   ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1106 
   1107   android_dlextinfo extinfo;
   1108   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1109   extinfo.library_namespace = ns;
   1110 
   1111   android_set_application_target_sdk_version(__ANDROID_API_M__);
   1112   void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
   1113   ASSERT_TRUE(handle == nullptr);
   1114   ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
   1115 }
   1116 
   1117 TEST(dlext, ns_cyclic_namespaces) {
   1118   // Test that ns1->ns2->ns1 link does not break the loader
   1119   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
   1120   std::string shared_libs = g_core_shared_libs + ":libthatdoesnotexist.so";
   1121 
   1122   const std::string ns_search_path =  get_testlib_root() + "/public_namespace_libs";
   1123 
   1124   android_namespace_t* ns1 =
   1125           android_create_namespace("ns1",
   1126                                    nullptr,
   1127                                    ns_search_path.c_str(),
   1128                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
   1129                                    nullptr,
   1130                                    nullptr);
   1131 
   1132   ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1133 
   1134   android_namespace_t* ns2 =
   1135           android_create_namespace("ns1",
   1136                                    nullptr,
   1137                                    ns_search_path.c_str(),
   1138                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
   1139                                    nullptr,
   1140                                    nullptr);
   1141 
   1142   ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1143 
   1144   ASSERT_TRUE(android_link_namespaces(ns2, ns1, shared_libs.c_str())) << dlerror();
   1145   ASSERT_TRUE(android_link_namespaces(ns1, ns2, shared_libs.c_str())) << dlerror();
   1146 
   1147   android_dlextinfo extinfo;
   1148   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1149   extinfo.library_namespace = ns1;
   1150 
   1151   void* handle = android_dlopen_ext("libthatdoesnotexist.so", RTLD_NOW, &extinfo);
   1152   ASSERT_TRUE(handle == nullptr);
   1153   ASSERT_STREQ("dlopen failed: library \"libthatdoesnotexist.so\" not found", dlerror());
   1154 }
   1155 
   1156 TEST(dlext, ns_isolated) {
   1157   static const char* root_lib = "libnstest_root_not_isolated.so";
   1158   std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
   1159 
   1160   const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib;
   1161   void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
   1162   ASSERT_TRUE(handle_public != nullptr) << dlerror();
   1163 
   1164   android_set_application_target_sdk_version(42U); // something > 23
   1165 
   1166   ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
   1167 
   1168   android_namespace_t* ns_not_isolated =
   1169           android_create_namespace("private",
   1170                                    nullptr,
   1171                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
   1172                                    ANDROID_NAMESPACE_TYPE_REGULAR,
   1173                                    nullptr,
   1174                                    nullptr);
   1175   ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
   1176   ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror();
   1177 
   1178   android_namespace_t* ns_isolated =
   1179           android_create_namespace("private_isolated1",
   1180                                    nullptr,
   1181                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
   1182                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
   1183                                    nullptr,
   1184                                    nullptr);
   1185   ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
   1186   ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, shared_libs.c_str())) << dlerror();
   1187 
   1188   android_namespace_t* ns_isolated2 =
   1189           android_create_namespace("private_isolated2",
   1190                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
   1191                                    nullptr,
   1192                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
   1193                                    get_testlib_root().c_str(),
   1194                                    nullptr);
   1195   ASSERT_TRUE(ns_isolated2 != nullptr) << dlerror();
   1196   ASSERT_TRUE(android_link_namespaces(ns_isolated2, nullptr, shared_libs.c_str())) << dlerror();
   1197 
   1198   ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
   1199   ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
   1200 
   1201   std::string lib_private_external_path =
   1202       get_testlib_root() + "/private_namespace_libs_external/libnstest_private_external.so";
   1203 
   1204   // Load lib_private_external_path to default namespace
   1205   // (it should remain invisible for the isolated namespaces after this)
   1206   void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
   1207   ASSERT_TRUE(handle != nullptr) << dlerror();
   1208 
   1209   android_dlextinfo extinfo;
   1210   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1211   extinfo.library_namespace = ns_not_isolated;
   1212 
   1213   void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
   1214   ASSERT_TRUE(handle1 != nullptr) << dlerror();
   1215 
   1216   extinfo.library_namespace = ns_isolated;
   1217 
   1218   void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
   1219   ASSERT_TRUE(handle2 == nullptr);
   1220   ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
   1221 
   1222   // Check dlopen by absolute path
   1223   handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
   1224   ASSERT_TRUE(handle2 == nullptr);
   1225   ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
   1226             " or dlopened by \"" + get_executable_path() +  "\" is not accessible"
   1227             " for the namespace \"private_isolated1\"", dlerror());
   1228 
   1229   extinfo.library_namespace = ns_isolated2;
   1230 
   1231   // this should work because isolation_path for private_isolated2 includes get_testlib_root()
   1232   handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
   1233   ASSERT_TRUE(handle2 != nullptr) << dlerror();
   1234   dlclose(handle2);
   1235 
   1236   // Check dlopen by absolute path
   1237   handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
   1238   ASSERT_TRUE(handle2 != nullptr) << dlerror();
   1239   dlclose(handle2);
   1240 
   1241   typedef const char* (*fn_t)();
   1242   fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
   1243   ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
   1244 
   1245   ASSERT_STREQ("This string is local to root library", ns_get_local_string());
   1246 
   1247   fn_t ns_get_private_extern_string =
   1248           reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
   1249   ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
   1250 
   1251   ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
   1252 
   1253   fn_t ns_get_public_extern_string =
   1254           reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
   1255   ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
   1256 
   1257   ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
   1258 
   1259   fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
   1260   ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
   1261 
   1262   ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
   1263 
   1264   dlclose(handle1);
   1265 }
   1266 
   1267 TEST(dlext, ns_shared) {
   1268   static const char* root_lib = "libnstest_root_not_isolated.so";
   1269   static const char* root_lib_isolated = "libnstest_root.so";
   1270 
   1271   std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
   1272 
   1273   // create a parent namespace to use instead of the default namespace. This is
   1274   // to make this test be independent from the configuration of the default
   1275   // namespace.
   1276   android_namespace_t* ns_parent =
   1277           android_create_namespace("parent",
   1278                                    nullptr,
   1279                                    nullptr,
   1280                                    ANDROID_NAMESPACE_TYPE_REGULAR,
   1281                                    nullptr,
   1282                                    nullptr);
   1283   ASSERT_TRUE(ns_parent != nullptr) << dlerror();
   1284   ASSERT_TRUE(android_link_namespaces(ns_parent, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1285 
   1286   android_dlextinfo extinfo;
   1287   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1288   extinfo.library_namespace = ns_parent;
   1289 
   1290   const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib;
   1291   void* handle_public = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
   1292   ASSERT_TRUE(handle_public != nullptr) << dlerror();
   1293 
   1294   android_set_application_target_sdk_version(42U); // something > 23
   1295 
   1296   ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
   1297 
   1298   // preload this library to the parent namespace to check if it
   1299   // is shared later on.
   1300   void* handle_dlopened =
   1301           android_dlopen_ext((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW, &extinfo);
   1302   ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
   1303 
   1304   // create two child namespaces of 'ns_parent'. One with regular, the other
   1305   // with isolated & shared.
   1306   android_namespace_t* ns_not_isolated =
   1307           android_create_namespace("private",
   1308                                    nullptr,
   1309                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
   1310                                    ANDROID_NAMESPACE_TYPE_REGULAR,
   1311                                    nullptr,
   1312                                    ns_parent);
   1313   ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
   1314   ASSERT_TRUE(android_link_namespaces(ns_not_isolated, ns_parent, g_public_lib)) << dlerror();
   1315   ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1316 
   1317   android_namespace_t* ns_isolated_shared =
   1318           android_create_namespace("private_isolated_shared",
   1319                                    nullptr,
   1320                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
   1321                                    ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
   1322                                    nullptr,
   1323                                    ns_parent);
   1324   ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
   1325   ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, ns_parent, g_public_lib)) << dlerror();
   1326   ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1327 
   1328   ASSERT_TRUE(android_dlopen_ext(root_lib, RTLD_NOW, &extinfo) == nullptr);
   1329   ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
   1330 
   1331   std::string lib_private_external_path =
   1332       get_testlib_root() + "/private_namespace_libs_external/libnstest_private_external.so";
   1333 
   1334   // Load lib_private_external_path to the parent namespace
   1335   // (it should remain invisible for the isolated namespaces after this)
   1336   void* handle = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
   1337   ASSERT_TRUE(handle != nullptr) << dlerror();
   1338 
   1339   extinfo.library_namespace = ns_not_isolated;
   1340 
   1341   void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
   1342   ASSERT_TRUE(handle1 != nullptr) << dlerror();
   1343 
   1344   extinfo.library_namespace = ns_isolated_shared;
   1345 
   1346   void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
   1347   ASSERT_TRUE(handle2 == nullptr);
   1348   ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
   1349 
   1350   // Check dlopen by absolute path
   1351   handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
   1352   ASSERT_TRUE(handle2 == nullptr);
   1353   ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
   1354             " or dlopened by \"" + get_executable_path() + "\" is not accessible"
   1355             " for the namespace \"private_isolated_shared\"", dlerror());
   1356 
   1357   // load libnstest_root.so to shared namespace in order to check that everything is different
   1358   // except shared libnstest_dlopened.so
   1359 
   1360   handle2 = android_dlopen_ext(root_lib_isolated, RTLD_NOW, &extinfo);
   1361 
   1362   typedef const char* (*fn_t)();
   1363   fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
   1364   ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
   1365   fn_t ns_get_local_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
   1366   ASSERT_TRUE(ns_get_local_string_shared != nullptr) << dlerror();
   1367 
   1368   ASSERT_STREQ("This string is local to root library", ns_get_local_string());
   1369   ASSERT_STREQ("This string is local to root library", ns_get_local_string_shared());
   1370   ASSERT_TRUE(ns_get_local_string() != ns_get_local_string_shared());
   1371 
   1372   fn_t ns_get_private_extern_string =
   1373           reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
   1374   ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
   1375   fn_t ns_get_private_extern_string_shared =
   1376           reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
   1377   ASSERT_TRUE(ns_get_private_extern_string_shared() != nullptr) << dlerror();
   1378 
   1379   ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
   1380   ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string_shared());
   1381   ASSERT_TRUE(ns_get_private_extern_string() != ns_get_private_extern_string_shared());
   1382 
   1383   fn_t ns_get_public_extern_string =
   1384           reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
   1385   ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
   1386   fn_t ns_get_public_extern_string_shared =
   1387           reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
   1388   ASSERT_TRUE(ns_get_public_extern_string_shared != nullptr) << dlerror();
   1389 
   1390   ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
   1391   ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string_shared());
   1392   ASSERT_TRUE(ns_get_public_extern_string() == ns_get_public_extern_string_shared());
   1393 
   1394   fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
   1395   ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
   1396   fn_t ns_get_dlopened_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
   1397   ASSERT_TRUE(ns_get_dlopened_string_shared != nullptr) << dlerror();
   1398   const char** ns_dlopened_string = static_cast<const char**>(dlsym(handle_dlopened, "g_private_dlopened_string"));
   1399   ASSERT_TRUE(ns_dlopened_string != nullptr) << dlerror();
   1400 
   1401   ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
   1402   ASSERT_STREQ("This string is from private namespace (dlopened library)", *ns_dlopened_string);
   1403   ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string_shared());
   1404   ASSERT_TRUE(ns_get_dlopened_string() != ns_get_dlopened_string_shared());
   1405   ASSERT_TRUE(*ns_dlopened_string == ns_get_dlopened_string_shared());
   1406 
   1407   dlclose(handle1);
   1408   dlclose(handle2);
   1409 }
   1410 
   1411 TEST(dlext, ns_shared_links_and_paths) {
   1412   // Create parent namespace (isolated, not shared)
   1413   android_namespace_t* ns_isolated =
   1414           android_create_namespace("private_isolated",
   1415                                    nullptr,
   1416                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
   1417                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
   1418                                    (get_testlib_root() + "/public_namespace_libs").c_str(),
   1419                                    nullptr);
   1420   ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
   1421   ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1422 
   1423   // Create shared namespace with ns_isolated parent
   1424   android_namespace_t* ns_shared =
   1425           android_create_namespace("private_shared",
   1426                                    nullptr,
   1427                                    nullptr,
   1428                                    ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
   1429                                    nullptr,
   1430                                    ns_isolated);
   1431   ASSERT_TRUE(ns_shared != nullptr) << dlerror();
   1432 
   1433   // 1. Load a library in ns_shared to check that it has inherited
   1434   // search path and the link to the default namespace.
   1435   android_dlextinfo extinfo;
   1436   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1437   extinfo.library_namespace = ns_shared;
   1438 
   1439   {
   1440     void* handle = android_dlopen_ext("libnstest_private.so", RTLD_NOW, &extinfo);
   1441     ASSERT_TRUE(handle != nullptr) << dlerror();
   1442     const char** ns_private_extern_string = static_cast<const char**>(dlsym(handle, "g_private_extern_string"));
   1443     ASSERT_TRUE(ns_private_extern_string != nullptr) << dlerror();
   1444     ASSERT_STREQ("This string is from private namespace", *ns_private_extern_string);
   1445 
   1446     dlclose(handle);
   1447   }
   1448   // 2. Load another test library by absolute path to check that
   1449   // it has inherited permitted_when_isolated_path
   1450   {
   1451     void* handle = android_dlopen_ext(
   1452             (get_testlib_root() + "/public_namespace_libs/libnstest_public.so").c_str(),
   1453             RTLD_NOW,
   1454             &extinfo);
   1455 
   1456     ASSERT_TRUE(handle != nullptr) << dlerror();
   1457     const char** ns_public_extern_string = static_cast<const char**>(dlsym(handle, "g_public_extern_string"));
   1458     ASSERT_TRUE(ns_public_extern_string != nullptr) << dlerror();
   1459     ASSERT_STREQ("This string is from public namespace", *ns_public_extern_string);
   1460 
   1461     dlclose(handle);
   1462   }
   1463 
   1464   // 3. Check that it is still isolated.
   1465   {
   1466     void* handle = android_dlopen_ext(
   1467             (get_testlib_root() + "/libtest_empty.so").c_str(),
   1468             RTLD_NOW,
   1469             &extinfo);
   1470 
   1471     ASSERT_TRUE(handle == nullptr);
   1472   }
   1473 }
   1474 
   1475 TEST(dlext, ns_shared_dlclose) {
   1476   android_set_application_target_sdk_version(42U); // something > 23
   1477 
   1478   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)) << dlerror();
   1479 
   1480   // preload this library to the default namespace to check if it
   1481   // is shared later on.
   1482   void* handle_dlopened =
   1483           dlopen((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
   1484   ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
   1485 
   1486   android_namespace_t* ns_isolated_shared =
   1487           android_create_namespace("private_isolated_shared",
   1488                                    nullptr,
   1489                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
   1490                                    ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
   1491                                    nullptr,
   1492                                    nullptr);
   1493   ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
   1494   ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1495 
   1496   // Check if "libnstest_dlopened.so" is loaded (and the same)
   1497   android_dlextinfo extinfo;
   1498   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1499   extinfo.library_namespace = ns_isolated_shared;
   1500 
   1501   void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
   1502   ASSERT_TRUE(handle != nullptr) << dlerror();
   1503   ASSERT_TRUE(handle == handle_dlopened);
   1504   dlclose(handle);
   1505   dlclose(handle_dlopened);
   1506 
   1507   // And now check that the library cannot be found by soname (and is no longer loaded)
   1508   handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
   1509   ASSERT_TRUE(handle == nullptr)
   1510       << "Error: libnstest_dlopened.so is still accessible in shared namespace";
   1511 
   1512   handle = android_dlopen_ext((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
   1513                               RTLD_NOW | RTLD_NOLOAD, &extinfo);
   1514   ASSERT_TRUE(handle == nullptr)
   1515       << "Error: libnstest_dlopened.so is still accessible in shared namespace";
   1516 
   1517   handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD);
   1518   ASSERT_TRUE(handle == nullptr)
   1519       << "Error: libnstest_dlopened.so is still accessible in default namespace";
   1520 
   1521   handle = dlopen((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
   1522                   RTLD_NOW | RTLD_NOLOAD);
   1523   ASSERT_TRUE(handle == nullptr)
   1524       << "Error: libnstest_dlopened.so is still accessible in default namespace";
   1525 
   1526   // Now lets see if the soinfo area gets reused in the wrong way:
   1527   // load a library to default namespace.
   1528   const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib;
   1529   void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
   1530   ASSERT_TRUE(handle_public != nullptr) << dlerror();
   1531 
   1532   // try to find it in shared namespace
   1533   handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
   1534   ASSERT_TRUE(handle == nullptr)
   1535       << "Error: " << g_public_lib << " is accessible in shared namespace";
   1536 }
   1537 
   1538 TEST(dlext, ns_isolated_rtld_global) {
   1539   static const char* root_lib = "libnstest_root.so";
   1540   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
   1541 
   1542   const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs";
   1543 
   1544   android_namespace_t* ns1 =
   1545           android_create_namespace("isolated1",
   1546                                    nullptr,
   1547                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
   1548                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
   1549                                    lib_public_path.c_str(),
   1550                                    nullptr);
   1551   ASSERT_TRUE(ns1 != nullptr) << dlerror();
   1552   ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1553 
   1554   android_namespace_t* ns2 =
   1555           android_create_namespace("isolated2",
   1556                                    nullptr,
   1557                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
   1558                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
   1559                                    lib_public_path.c_str(),
   1560                                    nullptr);
   1561   ASSERT_TRUE(ns2 != nullptr) << dlerror();
   1562   ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1563 
   1564   android_dlextinfo extinfo;
   1565   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1566   extinfo.library_namespace = ns1;
   1567 
   1568   void* handle_global = android_dlopen_ext((lib_public_path + "/" + g_public_lib).c_str(),
   1569                                            RTLD_GLOBAL,
   1570                                            &extinfo);
   1571 
   1572   ASSERT_TRUE(handle_global != nullptr) << dlerror();
   1573 
   1574   android_namespace_t* ns1_child =
   1575           android_create_namespace("isolated1_child",
   1576                                    nullptr,
   1577                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
   1578                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
   1579                                    nullptr,
   1580                                    ns1);
   1581 
   1582   ASSERT_TRUE(ns1_child != nullptr) << dlerror();
   1583   ASSERT_TRUE(android_link_namespaces(ns1_child, nullptr, g_core_shared_libs.c_str())) << dlerror();
   1584 
   1585   // Now - only ns1 and ns1 child should be able to dlopen root_lib
   1586   // attempt to use ns2 should result in dlerror()
   1587 
   1588   // Check ns1_child first.
   1589   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1590   extinfo.library_namespace = ns1_child;
   1591 
   1592   void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
   1593   ASSERT_TRUE(handle1 != nullptr) << dlerror();
   1594 
   1595   // now ns1
   1596   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1597   extinfo.library_namespace = ns1;
   1598 
   1599   handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
   1600   ASSERT_TRUE(handle1 != nullptr) << dlerror();
   1601 
   1602   // and ns2 should fail
   1603   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1604   extinfo.library_namespace = ns2;
   1605 
   1606   handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
   1607   ASSERT_TRUE(handle1 == nullptr);
   1608   ASSERT_STREQ("dlopen failed: library \"libnstest_public.so\" not found", dlerror());
   1609 }
   1610 
   1611 TEST(dlext, ns_anonymous) {
   1612   static const char* root_lib = "libnstest_root.so";
   1613   std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
   1614 
   1615   const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib;
   1616   void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
   1617 
   1618   ASSERT_TRUE(handle_public != nullptr) << dlerror();
   1619 
   1620   ASSERT_TRUE(
   1621           android_init_anonymous_namespace(shared_libs.c_str(),
   1622                                            (get_testlib_root() + "/private_namespace_libs").c_str())
   1623       ) << dlerror();
   1624 
   1625   android_namespace_t* ns =
   1626           android_create_namespace("private",
   1627                                    nullptr,
   1628                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
   1629                                    ANDROID_NAMESPACE_TYPE_REGULAR,
   1630                                    nullptr,
   1631                                    nullptr);
   1632 
   1633   ASSERT_TRUE(ns != nullptr) << dlerror();
   1634   ASSERT_TRUE(android_link_namespaces(ns, nullptr, shared_libs.c_str())) << dlerror();
   1635 
   1636   std::string private_library_absolute_path = get_testlib_root() + "/private_namespace_libs/" + root_lib;
   1637 
   1638   android_dlextinfo extinfo;
   1639   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   1640   extinfo.library_namespace = ns;
   1641 
   1642   // we are going to copy this library to anonymous mmap and call the copy of ns_get_dlopened_string
   1643   void* handle = android_dlopen_ext(private_library_absolute_path.c_str(), RTLD_NOW, &extinfo);
   1644   ASSERT_TRUE(handle != nullptr) << dlerror();
   1645 
   1646   uintptr_t ns_get_dlopened_string_addr =
   1647       reinterpret_cast<uintptr_t>(dlsym(handle, "ns_get_dlopened_string"));
   1648   ASSERT_TRUE(ns_get_dlopened_string_addr != 0) << dlerror();
   1649   typedef const char* (*fn_t)();
   1650   fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
   1651 
   1652   std::vector<map_record> maps;
   1653   Maps::parse_maps(&maps);
   1654 
   1655   uintptr_t addr_start = 0;
   1656   uintptr_t addr_end = 0;
   1657   std::vector<map_record> maps_to_copy;
   1658 
   1659   for (const auto& rec : maps) {
   1660     if (rec.pathname == private_library_absolute_path) {
   1661       if (addr_start == 0) {
   1662         addr_start = rec.addr_start;
   1663       }
   1664       addr_end = rec.addr_end;
   1665 
   1666       maps_to_copy.push_back(rec);
   1667     }
   1668   }
   1669 
   1670   // some sanity checks..
   1671   ASSERT_TRUE(addr_start > 0);
   1672   ASSERT_TRUE(addr_end > 0);
   1673   ASSERT_EQ(3U, maps_to_copy.size());
   1674   ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
   1675   ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
   1676 
   1677   // copy
   1678   uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start,
   1679                                                              PROT_NONE, MAP_ANON | MAP_PRIVATE,
   1680                                                              -1, 0));
   1681   ASSERT_TRUE(reinterpret_cast<void*>(reserved_addr) != MAP_FAILED);
   1682 
   1683   for (const auto& rec : maps_to_copy) {
   1684     uintptr_t offset = rec.addr_start - addr_start;
   1685     size_t size = rec.addr_end - rec.addr_start;
   1686     void* addr = reinterpret_cast<void*>(reserved_addr + offset);
   1687     void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
   1688                      MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
   1689     ASSERT_TRUE(map != MAP_FAILED);
   1690     memcpy(map, reinterpret_cast<void*>(rec.addr_start), size);
   1691     mprotect(map, size, rec.perms);
   1692   }
   1693 
   1694   // call the function copy
   1695   uintptr_t ns_get_dlopened_string_offset  = ns_get_dlopened_string_addr - addr_start;
   1696   fn_t ns_get_dlopened_string_anon = reinterpret_cast<fn_t>(reserved_addr + ns_get_dlopened_string_offset);
   1697   ASSERT_STREQ("This string is from private namespace (dlopened library)",
   1698                ns_get_dlopened_string_anon());
   1699 
   1700   // They should belong to different namespaces (private and anonymous)
   1701   ASSERT_STREQ("This string is from private namespace (dlopened library)",
   1702                ns_get_dlopened_string_private());
   1703 
   1704   ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private());
   1705 }
   1706 
   1707 TEST(dlext, dlopen_handle_value_platform) {
   1708   void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
   1709   ASSERT_TRUE((reinterpret_cast<uintptr_t>(handle) & 1) != 0)
   1710           << "dlopen should return odd value for the handle";
   1711   dlclose(handle);
   1712 }
   1713 
   1714 TEST(dlext, dlopen_handle_value_app_compat) {
   1715   android_set_application_target_sdk_version(__ANDROID_API_M__);
   1716   void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
   1717   ASSERT_TRUE(reinterpret_cast<uintptr_t>(handle) % sizeof(uintptr_t) == 0)
   1718           << "dlopen should return valid pointer";
   1719   dlclose(handle);
   1720 }
   1721