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