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