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