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