OSDN Git Service

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