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); 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); 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)); 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_greylist_enabled) { 1055 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)); 1056 1057 const std::string ns_search_path = get_testlib_root() + "/private_namespace_libs"; 1058 1059 android_namespace_t* ns = 1060 android_create_namespace("namespace", 1061 nullptr, 1062 ns_search_path.c_str(), 1063 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED, 1064 nullptr, 1065 nullptr); 1066 1067 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1068 1069 android_dlextinfo extinfo; 1070 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1071 extinfo.library_namespace = ns; 1072 1073 // An app targeting M can open libnativehelper.so because it's on the greylist. 1074 android_set_application_target_sdk_version(__ANDROID_API_M__); 1075 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo); 1076 ASSERT_TRUE(handle != nullptr) << dlerror(); 1077 1078 // Check that loader did not load another copy of libdl.so while loading greylisted library. 1079 void* dlsym_ptr = dlsym(handle, "dlsym"); 1080 ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror(); 1081 ASSERT_EQ(&dlsym, dlsym_ptr); 1082 1083 dlclose(handle); 1084 1085 // An app targeting N no longer has the greylist. 1086 android_set_application_target_sdk_version(__ANDROID_API_N__); 1087 handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo); 1088 ASSERT_TRUE(handle == nullptr); 1089 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror()); 1090 } 1091 1092 TEST(dlext, ns_greylist_disabled_by_default) { 1093 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)); 1094 1095 const std::string ns_search_path = get_testlib_root() + "/private_namespace_libs"; 1096 1097 android_namespace_t* ns = 1098 android_create_namespace("namespace", 1099 nullptr, 1100 ns_search_path.c_str(), 1101 ANDROID_NAMESPACE_TYPE_ISOLATED, 1102 nullptr, 1103 nullptr); 1104 1105 ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1106 1107 android_dlextinfo extinfo; 1108 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1109 extinfo.library_namespace = ns; 1110 1111 android_set_application_target_sdk_version(__ANDROID_API_M__); 1112 void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo); 1113 ASSERT_TRUE(handle == nullptr); 1114 ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror()); 1115 } 1116 1117 TEST(dlext, ns_cyclic_namespaces) { 1118 // Test that ns1->ns2->ns1 link does not break the loader 1119 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)); 1120 std::string shared_libs = g_core_shared_libs + ":libthatdoesnotexist.so"; 1121 1122 const std::string ns_search_path = get_testlib_root() + "/public_namespace_libs"; 1123 1124 android_namespace_t* ns1 = 1125 android_create_namespace("ns1", 1126 nullptr, 1127 ns_search_path.c_str(), 1128 ANDROID_NAMESPACE_TYPE_ISOLATED, 1129 nullptr, 1130 nullptr); 1131 1132 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1133 1134 android_namespace_t* ns2 = 1135 android_create_namespace("ns1", 1136 nullptr, 1137 ns_search_path.c_str(), 1138 ANDROID_NAMESPACE_TYPE_ISOLATED, 1139 nullptr, 1140 nullptr); 1141 1142 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1143 1144 ASSERT_TRUE(android_link_namespaces(ns2, ns1, shared_libs.c_str())) << dlerror(); 1145 ASSERT_TRUE(android_link_namespaces(ns1, ns2, shared_libs.c_str())) << dlerror(); 1146 1147 android_dlextinfo extinfo; 1148 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1149 extinfo.library_namespace = ns1; 1150 1151 void* handle = android_dlopen_ext("libthatdoesnotexist.so", RTLD_NOW, &extinfo); 1152 ASSERT_TRUE(handle == nullptr); 1153 ASSERT_STREQ("dlopen failed: library \"libthatdoesnotexist.so\" not found", dlerror()); 1154 } 1155 1156 TEST(dlext, ns_isolated) { 1157 static const char* root_lib = "libnstest_root_not_isolated.so"; 1158 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib; 1159 1160 const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib; 1161 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW); 1162 ASSERT_TRUE(handle_public != nullptr) << dlerror(); 1163 1164 android_set_application_target_sdk_version(42U); // something > 23 1165 1166 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror(); 1167 1168 android_namespace_t* ns_not_isolated = 1169 android_create_namespace("private", 1170 nullptr, 1171 (get_testlib_root() + "/private_namespace_libs").c_str(), 1172 ANDROID_NAMESPACE_TYPE_REGULAR, 1173 nullptr, 1174 nullptr); 1175 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror(); 1176 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror(); 1177 1178 android_namespace_t* ns_isolated = 1179 android_create_namespace("private_isolated1", 1180 nullptr, 1181 (get_testlib_root() + "/private_namespace_libs").c_str(), 1182 ANDROID_NAMESPACE_TYPE_ISOLATED, 1183 nullptr, 1184 nullptr); 1185 ASSERT_TRUE(ns_isolated != nullptr) << dlerror(); 1186 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, shared_libs.c_str())) << dlerror(); 1187 1188 android_namespace_t* ns_isolated2 = 1189 android_create_namespace("private_isolated2", 1190 (get_testlib_root() + "/private_namespace_libs").c_str(), 1191 nullptr, 1192 ANDROID_NAMESPACE_TYPE_ISOLATED, 1193 get_testlib_root().c_str(), 1194 nullptr); 1195 ASSERT_TRUE(ns_isolated2 != nullptr) << dlerror(); 1196 ASSERT_TRUE(android_link_namespaces(ns_isolated2, nullptr, shared_libs.c_str())) << dlerror(); 1197 1198 ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr); 1199 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror()); 1200 1201 std::string lib_private_external_path = 1202 get_testlib_root() + "/private_namespace_libs_external/libnstest_private_external.so"; 1203 1204 // Load lib_private_external_path to default namespace 1205 // (it should remain invisible for the isolated namespaces after this) 1206 void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW); 1207 ASSERT_TRUE(handle != nullptr) << dlerror(); 1208 1209 android_dlextinfo extinfo; 1210 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1211 extinfo.library_namespace = ns_not_isolated; 1212 1213 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo); 1214 ASSERT_TRUE(handle1 != nullptr) << dlerror(); 1215 1216 extinfo.library_namespace = ns_isolated; 1217 1218 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo); 1219 ASSERT_TRUE(handle2 == nullptr); 1220 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror()); 1221 1222 // Check dlopen by absolute path 1223 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo); 1224 ASSERT_TRUE(handle2 == nullptr); 1225 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed" 1226 " or dlopened by \"" + get_executable_path() + "\" is not accessible" 1227 " for the namespace \"private_isolated1\"", dlerror()); 1228 1229 extinfo.library_namespace = ns_isolated2; 1230 1231 // this should work because isolation_path for private_isolated2 includes get_testlib_root() 1232 handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo); 1233 ASSERT_TRUE(handle2 != nullptr) << dlerror(); 1234 dlclose(handle2); 1235 1236 // Check dlopen by absolute path 1237 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo); 1238 ASSERT_TRUE(handle2 != nullptr) << dlerror(); 1239 dlclose(handle2); 1240 1241 typedef const char* (*fn_t)(); 1242 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string")); 1243 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror(); 1244 1245 ASSERT_STREQ("This string is local to root library", ns_get_local_string()); 1246 1247 fn_t ns_get_private_extern_string = 1248 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string")); 1249 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror(); 1250 1251 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string()); 1252 1253 fn_t ns_get_public_extern_string = 1254 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string")); 1255 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror(); 1256 1257 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string()); 1258 1259 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string")); 1260 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror(); 1261 1262 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string()); 1263 1264 dlclose(handle1); 1265 } 1266 1267 TEST(dlext, ns_shared) { 1268 static const char* root_lib = "libnstest_root_not_isolated.so"; 1269 static const char* root_lib_isolated = "libnstest_root.so"; 1270 1271 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib; 1272 1273 // create a parent namespace to use instead of the default namespace. This is 1274 // to make this test be independent from the configuration of the default 1275 // namespace. 1276 android_namespace_t* ns_parent = 1277 android_create_namespace("parent", 1278 nullptr, 1279 nullptr, 1280 ANDROID_NAMESPACE_TYPE_REGULAR, 1281 nullptr, 1282 nullptr); 1283 ASSERT_TRUE(ns_parent != nullptr) << dlerror(); 1284 ASSERT_TRUE(android_link_namespaces(ns_parent, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1285 1286 android_dlextinfo extinfo; 1287 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1288 extinfo.library_namespace = ns_parent; 1289 1290 const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib; 1291 void* handle_public = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo); 1292 ASSERT_TRUE(handle_public != nullptr) << dlerror(); 1293 1294 android_set_application_target_sdk_version(42U); // something > 23 1295 1296 ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror(); 1297 1298 // preload this library to the parent namespace to check if it 1299 // is shared later on. 1300 void* handle_dlopened = 1301 android_dlopen_ext((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW, &extinfo); 1302 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror(); 1303 1304 // create two child namespaces of 'ns_parent'. One with regular, the other 1305 // with isolated & shared. 1306 android_namespace_t* ns_not_isolated = 1307 android_create_namespace("private", 1308 nullptr, 1309 (get_testlib_root() + "/private_namespace_libs").c_str(), 1310 ANDROID_NAMESPACE_TYPE_REGULAR, 1311 nullptr, 1312 ns_parent); 1313 ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror(); 1314 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, ns_parent, g_public_lib)) << dlerror(); 1315 ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1316 1317 android_namespace_t* ns_isolated_shared = 1318 android_create_namespace("private_isolated_shared", 1319 nullptr, 1320 (get_testlib_root() + "/private_namespace_libs").c_str(), 1321 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED, 1322 nullptr, 1323 ns_parent); 1324 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror(); 1325 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, ns_parent, g_public_lib)) << dlerror(); 1326 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1327 1328 ASSERT_TRUE(android_dlopen_ext(root_lib, RTLD_NOW, &extinfo) == nullptr); 1329 ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror()); 1330 1331 std::string lib_private_external_path = 1332 get_testlib_root() + "/private_namespace_libs_external/libnstest_private_external.so"; 1333 1334 // Load lib_private_external_path to the parent namespace 1335 // (it should remain invisible for the isolated namespaces after this) 1336 void* handle = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo); 1337 ASSERT_TRUE(handle != nullptr) << dlerror(); 1338 1339 extinfo.library_namespace = ns_not_isolated; 1340 1341 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo); 1342 ASSERT_TRUE(handle1 != nullptr) << dlerror(); 1343 1344 extinfo.library_namespace = ns_isolated_shared; 1345 1346 void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo); 1347 ASSERT_TRUE(handle2 == nullptr); 1348 ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror()); 1349 1350 // Check dlopen by absolute path 1351 handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo); 1352 ASSERT_TRUE(handle2 == nullptr); 1353 ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed" 1354 " or dlopened by \"" + get_executable_path() + "\" is not accessible" 1355 " for the namespace \"private_isolated_shared\"", dlerror()); 1356 1357 // load libnstest_root.so to shared namespace in order to check that everything is different 1358 // except shared libnstest_dlopened.so 1359 1360 handle2 = android_dlopen_ext(root_lib_isolated, RTLD_NOW, &extinfo); 1361 1362 typedef const char* (*fn_t)(); 1363 fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string")); 1364 ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror(); 1365 fn_t ns_get_local_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string")); 1366 ASSERT_TRUE(ns_get_local_string_shared != nullptr) << dlerror(); 1367 1368 ASSERT_STREQ("This string is local to root library", ns_get_local_string()); 1369 ASSERT_STREQ("This string is local to root library", ns_get_local_string_shared()); 1370 ASSERT_TRUE(ns_get_local_string() != ns_get_local_string_shared()); 1371 1372 fn_t ns_get_private_extern_string = 1373 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string")); 1374 ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror(); 1375 fn_t ns_get_private_extern_string_shared = 1376 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string")); 1377 ASSERT_TRUE(ns_get_private_extern_string_shared() != nullptr) << dlerror(); 1378 1379 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string()); 1380 ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string_shared()); 1381 ASSERT_TRUE(ns_get_private_extern_string() != ns_get_private_extern_string_shared()); 1382 1383 fn_t ns_get_public_extern_string = 1384 reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string")); 1385 ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror(); 1386 fn_t ns_get_public_extern_string_shared = 1387 reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string")); 1388 ASSERT_TRUE(ns_get_public_extern_string_shared != nullptr) << dlerror(); 1389 1390 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string()); 1391 ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string_shared()); 1392 ASSERT_TRUE(ns_get_public_extern_string() == ns_get_public_extern_string_shared()); 1393 1394 fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string")); 1395 ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror(); 1396 fn_t ns_get_dlopened_string_shared = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string")); 1397 ASSERT_TRUE(ns_get_dlopened_string_shared != nullptr) << dlerror(); 1398 const char** ns_dlopened_string = static_cast<const char**>(dlsym(handle_dlopened, "g_private_dlopened_string")); 1399 ASSERT_TRUE(ns_dlopened_string != nullptr) << dlerror(); 1400 1401 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string()); 1402 ASSERT_STREQ("This string is from private namespace (dlopened library)", *ns_dlopened_string); 1403 ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string_shared()); 1404 ASSERT_TRUE(ns_get_dlopened_string() != ns_get_dlopened_string_shared()); 1405 ASSERT_TRUE(*ns_dlopened_string == ns_get_dlopened_string_shared()); 1406 1407 dlclose(handle1); 1408 dlclose(handle2); 1409 } 1410 1411 TEST(dlext, ns_shared_links_and_paths) { 1412 // Create parent namespace (isolated, not shared) 1413 android_namespace_t* ns_isolated = 1414 android_create_namespace("private_isolated", 1415 nullptr, 1416 (get_testlib_root() + "/private_namespace_libs").c_str(), 1417 ANDROID_NAMESPACE_TYPE_ISOLATED, 1418 (get_testlib_root() + "/public_namespace_libs").c_str(), 1419 nullptr); 1420 ASSERT_TRUE(ns_isolated != nullptr) << dlerror(); 1421 ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1422 1423 // Create shared namespace with ns_isolated parent 1424 android_namespace_t* ns_shared = 1425 android_create_namespace("private_shared", 1426 nullptr, 1427 nullptr, 1428 ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED, 1429 nullptr, 1430 ns_isolated); 1431 ASSERT_TRUE(ns_shared != nullptr) << dlerror(); 1432 1433 // 1. Load a library in ns_shared to check that it has inherited 1434 // search path and the link to the default namespace. 1435 android_dlextinfo extinfo; 1436 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1437 extinfo.library_namespace = ns_shared; 1438 1439 { 1440 void* handle = android_dlopen_ext("libnstest_private.so", RTLD_NOW, &extinfo); 1441 ASSERT_TRUE(handle != nullptr) << dlerror(); 1442 const char** ns_private_extern_string = static_cast<const char**>(dlsym(handle, "g_private_extern_string")); 1443 ASSERT_TRUE(ns_private_extern_string != nullptr) << dlerror(); 1444 ASSERT_STREQ("This string is from private namespace", *ns_private_extern_string); 1445 1446 dlclose(handle); 1447 } 1448 // 2. Load another test library by absolute path to check that 1449 // it has inherited permitted_when_isolated_path 1450 { 1451 void* handle = android_dlopen_ext( 1452 (get_testlib_root() + "/public_namespace_libs/libnstest_public.so").c_str(), 1453 RTLD_NOW, 1454 &extinfo); 1455 1456 ASSERT_TRUE(handle != nullptr) << dlerror(); 1457 const char** ns_public_extern_string = static_cast<const char**>(dlsym(handle, "g_public_extern_string")); 1458 ASSERT_TRUE(ns_public_extern_string != nullptr) << dlerror(); 1459 ASSERT_STREQ("This string is from public namespace", *ns_public_extern_string); 1460 1461 dlclose(handle); 1462 } 1463 1464 // 3. Check that it is still isolated. 1465 { 1466 void* handle = android_dlopen_ext( 1467 (get_testlib_root() + "/libtest_empty.so").c_str(), 1468 RTLD_NOW, 1469 &extinfo); 1470 1471 ASSERT_TRUE(handle == nullptr); 1472 } 1473 } 1474 1475 TEST(dlext, ns_shared_dlclose) { 1476 android_set_application_target_sdk_version(42U); // something > 23 1477 1478 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)) << dlerror(); 1479 1480 // preload this library to the default namespace to check if it 1481 // is shared later on. 1482 void* handle_dlopened = 1483 dlopen((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW); 1484 ASSERT_TRUE(handle_dlopened != nullptr) << dlerror(); 1485 1486 android_namespace_t* ns_isolated_shared = 1487 android_create_namespace("private_isolated_shared", 1488 nullptr, 1489 (get_testlib_root() + "/private_namespace_libs").c_str(), 1490 ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED, 1491 nullptr, 1492 nullptr); 1493 ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror(); 1494 ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1495 1496 // Check if "libnstest_dlopened.so" is loaded (and the same) 1497 android_dlextinfo extinfo; 1498 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1499 extinfo.library_namespace = ns_isolated_shared; 1500 1501 void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo); 1502 ASSERT_TRUE(handle != nullptr) << dlerror(); 1503 ASSERT_TRUE(handle == handle_dlopened); 1504 dlclose(handle); 1505 dlclose(handle_dlopened); 1506 1507 // And now check that the library cannot be found by soname (and is no longer loaded) 1508 handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo); 1509 ASSERT_TRUE(handle == nullptr) 1510 << "Error: libnstest_dlopened.so is still accessible in shared namespace"; 1511 1512 handle = android_dlopen_ext((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), 1513 RTLD_NOW | RTLD_NOLOAD, &extinfo); 1514 ASSERT_TRUE(handle == nullptr) 1515 << "Error: libnstest_dlopened.so is still accessible in shared namespace"; 1516 1517 handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD); 1518 ASSERT_TRUE(handle == nullptr) 1519 << "Error: libnstest_dlopened.so is still accessible in default namespace"; 1520 1521 handle = dlopen((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), 1522 RTLD_NOW | RTLD_NOLOAD); 1523 ASSERT_TRUE(handle == nullptr) 1524 << "Error: libnstest_dlopened.so is still accessible in default namespace"; 1525 1526 // Now lets see if the soinfo area gets reused in the wrong way: 1527 // load a library to default namespace. 1528 const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib; 1529 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW); 1530 ASSERT_TRUE(handle_public != nullptr) << dlerror(); 1531 1532 // try to find it in shared namespace 1533 handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo); 1534 ASSERT_TRUE(handle == nullptr) 1535 << "Error: " << g_public_lib << " is accessible in shared namespace"; 1536 } 1537 1538 TEST(dlext, ns_isolated_rtld_global) { 1539 static const char* root_lib = "libnstest_root.so"; 1540 ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)); 1541 1542 const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs"; 1543 1544 android_namespace_t* ns1 = 1545 android_create_namespace("isolated1", 1546 nullptr, 1547 (get_testlib_root() + "/private_namespace_libs").c_str(), 1548 ANDROID_NAMESPACE_TYPE_ISOLATED, 1549 lib_public_path.c_str(), 1550 nullptr); 1551 ASSERT_TRUE(ns1 != nullptr) << dlerror(); 1552 ASSERT_TRUE(android_link_namespaces(ns1, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1553 1554 android_namespace_t* ns2 = 1555 android_create_namespace("isolated2", 1556 nullptr, 1557 (get_testlib_root() + "/private_namespace_libs").c_str(), 1558 ANDROID_NAMESPACE_TYPE_ISOLATED, 1559 lib_public_path.c_str(), 1560 nullptr); 1561 ASSERT_TRUE(ns2 != nullptr) << dlerror(); 1562 ASSERT_TRUE(android_link_namespaces(ns2, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1563 1564 android_dlextinfo extinfo; 1565 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1566 extinfo.library_namespace = ns1; 1567 1568 void* handle_global = android_dlopen_ext((lib_public_path + "/" + g_public_lib).c_str(), 1569 RTLD_GLOBAL, 1570 &extinfo); 1571 1572 ASSERT_TRUE(handle_global != nullptr) << dlerror(); 1573 1574 android_namespace_t* ns1_child = 1575 android_create_namespace("isolated1_child", 1576 nullptr, 1577 (get_testlib_root() + "/private_namespace_libs").c_str(), 1578 ANDROID_NAMESPACE_TYPE_ISOLATED, 1579 nullptr, 1580 ns1); 1581 1582 ASSERT_TRUE(ns1_child != nullptr) << dlerror(); 1583 ASSERT_TRUE(android_link_namespaces(ns1_child, nullptr, g_core_shared_libs.c_str())) << dlerror(); 1584 1585 // Now - only ns1 and ns1 child should be able to dlopen root_lib 1586 // attempt to use ns2 should result in dlerror() 1587 1588 // Check ns1_child first. 1589 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1590 extinfo.library_namespace = ns1_child; 1591 1592 void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo); 1593 ASSERT_TRUE(handle1 != nullptr) << dlerror(); 1594 1595 // now ns1 1596 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1597 extinfo.library_namespace = ns1; 1598 1599 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo); 1600 ASSERT_TRUE(handle1 != nullptr) << dlerror(); 1601 1602 // and ns2 should fail 1603 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1604 extinfo.library_namespace = ns2; 1605 1606 handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo); 1607 ASSERT_TRUE(handle1 == nullptr); 1608 ASSERT_STREQ("dlopen failed: library \"libnstest_public.so\" not found", dlerror()); 1609 } 1610 1611 TEST(dlext, ns_anonymous) { 1612 static const char* root_lib = "libnstest_root.so"; 1613 std::string shared_libs = g_core_shared_libs + ":" + g_public_lib; 1614 1615 const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib; 1616 void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW); 1617 1618 ASSERT_TRUE(handle_public != nullptr) << dlerror(); 1619 1620 ASSERT_TRUE( 1621 android_init_anonymous_namespace(shared_libs.c_str(), 1622 (get_testlib_root() + "/private_namespace_libs").c_str()) 1623 ) << dlerror(); 1624 1625 android_namespace_t* ns = 1626 android_create_namespace("private", 1627 nullptr, 1628 (get_testlib_root() + "/private_namespace_libs").c_str(), 1629 ANDROID_NAMESPACE_TYPE_REGULAR, 1630 nullptr, 1631 nullptr); 1632 1633 ASSERT_TRUE(ns != nullptr) << dlerror(); 1634 ASSERT_TRUE(android_link_namespaces(ns, nullptr, shared_libs.c_str())) << dlerror(); 1635 1636 std::string private_library_absolute_path = get_testlib_root() + "/private_namespace_libs/" + root_lib; 1637 1638 android_dlextinfo extinfo; 1639 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 1640 extinfo.library_namespace = ns; 1641 1642 // we are going to copy this library to anonymous mmap and call the copy of ns_get_dlopened_string 1643 void* handle = android_dlopen_ext(private_library_absolute_path.c_str(), RTLD_NOW, &extinfo); 1644 ASSERT_TRUE(handle != nullptr) << dlerror(); 1645 1646 uintptr_t ns_get_dlopened_string_addr = 1647 reinterpret_cast<uintptr_t>(dlsym(handle, "ns_get_dlopened_string")); 1648 ASSERT_TRUE(ns_get_dlopened_string_addr != 0) << dlerror(); 1649 typedef const char* (*fn_t)(); 1650 fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr); 1651 1652 std::vector<map_record> maps; 1653 Maps::parse_maps(&maps); 1654 1655 uintptr_t addr_start = 0; 1656 uintptr_t addr_end = 0; 1657 std::vector<map_record> maps_to_copy; 1658 1659 for (const auto& rec : maps) { 1660 if (rec.pathname == private_library_absolute_path) { 1661 if (addr_start == 0) { 1662 addr_start = rec.addr_start; 1663 } 1664 addr_end = rec.addr_end; 1665 1666 maps_to_copy.push_back(rec); 1667 } 1668 } 1669 1670 // some sanity checks.. 1671 ASSERT_TRUE(addr_start > 0); 1672 ASSERT_TRUE(addr_end > 0); 1673 ASSERT_EQ(3U, maps_to_copy.size()); 1674 ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start); 1675 ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end); 1676 1677 // copy 1678 uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start, 1679 PROT_NONE, MAP_ANON | MAP_PRIVATE, 1680 -1, 0)); 1681 ASSERT_TRUE(reinterpret_cast<void*>(reserved_addr) != MAP_FAILED); 1682 1683 for (const auto& rec : maps_to_copy) { 1684 uintptr_t offset = rec.addr_start - addr_start; 1685 size_t size = rec.addr_end - rec.addr_start; 1686 void* addr = reinterpret_cast<void*>(reserved_addr + offset); 1687 void* map = mmap(addr, size, PROT_READ | PROT_WRITE, 1688 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); 1689 ASSERT_TRUE(map != MAP_FAILED); 1690 memcpy(map, reinterpret_cast<void*>(rec.addr_start), size); 1691 mprotect(map, size, rec.perms); 1692 } 1693 1694 // call the function copy 1695 uintptr_t ns_get_dlopened_string_offset = ns_get_dlopened_string_addr - addr_start; 1696 fn_t ns_get_dlopened_string_anon = reinterpret_cast<fn_t>(reserved_addr + ns_get_dlopened_string_offset); 1697 ASSERT_STREQ("This string is from private namespace (dlopened library)", 1698 ns_get_dlopened_string_anon()); 1699 1700 // They should belong to different namespaces (private and anonymous) 1701 ASSERT_STREQ("This string is from private namespace (dlopened library)", 1702 ns_get_dlopened_string_private()); 1703 1704 ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private()); 1705 } 1706 1707 TEST(dlext, dlopen_handle_value_platform) { 1708 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL); 1709 ASSERT_TRUE((reinterpret_cast<uintptr_t>(handle) & 1) != 0) 1710 << "dlopen should return odd value for the handle"; 1711 dlclose(handle); 1712 } 1713 1714 TEST(dlext, dlopen_handle_value_app_compat) { 1715 android_set_application_target_sdk_version(__ANDROID_API_M__); 1716 void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL); 1717 ASSERT_TRUE(reinterpret_cast<uintptr_t>(handle) % sizeof(uintptr_t) == 0) 1718 << "dlopen should return valid pointer"; 1719 dlclose(handle); 1720 } 1721