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: 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 81 void TearDown() override { 82 if (handle_ != nullptr) { 83 ASSERT_DL_ZERO(dlclose(handle_)); 84 } 85 } 86 87 void* handle_; 88 }; 89 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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: 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 431 void TearDown() override { 432 DlExtTest::TearDown(); 433 } 434 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 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 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 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 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 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 572 TEST_F(DlExtRelroSharingTest, RelroFileEmpty) { 573 ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName, false)); 574 } 575 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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