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