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