1 /* 2 * Copyright (C) 2015 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 "nativeloader/native_loader.h" 18 #include <nativehelper/ScopedUtfChars.h> 19 20 #include <dlfcn.h> 21 #ifdef __ANDROID__ 22 #define LOG_TAG "libnativeloader" 23 #include "nativeloader/dlext_namespaces.h" 24 #include "cutils/properties.h" 25 #include "log/log.h" 26 #endif 27 #include <dirent.h> 28 #include <sys/types.h> 29 #include "nativebridge/native_bridge.h" 30 31 #include <algorithm> 32 #include <memory> 33 #include <mutex> 34 #include <string> 35 #include <vector> 36 37 #include <android-base/file.h> 38 #include <android-base/macros.h> 39 #include <android-base/strings.h> 40 41 #ifdef __BIONIC__ 42 #include <android-base/properties.h> 43 #endif 44 45 #define CHECK(predicate) LOG_ALWAYS_FATAL_IF(!(predicate),\ 46 "%s:%d: %s CHECK '" #predicate "' failed.",\ 47 __FILE__, __LINE__, __FUNCTION__) 48 49 using namespace std::string_literals; 50 51 namespace android { 52 53 #if defined(__ANDROID__) 54 class NativeLoaderNamespace { 55 public: 56 NativeLoaderNamespace() 57 : android_ns_(nullptr), native_bridge_ns_(nullptr) { } 58 59 explicit NativeLoaderNamespace(android_namespace_t* ns) 60 : android_ns_(ns), native_bridge_ns_(nullptr) { } 61 62 explicit NativeLoaderNamespace(native_bridge_namespace_t* ns) 63 : android_ns_(nullptr), native_bridge_ns_(ns) { } 64 65 NativeLoaderNamespace(NativeLoaderNamespace&& that) = default; 66 NativeLoaderNamespace(const NativeLoaderNamespace& that) = default; 67 68 NativeLoaderNamespace& operator=(const NativeLoaderNamespace& that) = default; 69 70 android_namespace_t* get_android_ns() const { 71 CHECK(native_bridge_ns_ == nullptr); 72 return android_ns_; 73 } 74 75 native_bridge_namespace_t* get_native_bridge_ns() const { 76 CHECK(android_ns_ == nullptr); 77 return native_bridge_ns_; 78 } 79 80 bool is_android_namespace() const { 81 return native_bridge_ns_ == nullptr; 82 } 83 84 private: 85 // Only one of them can be not null 86 android_namespace_t* android_ns_; 87 native_bridge_namespace_t* native_bridge_ns_; 88 }; 89 90 static constexpr const char kPublicNativeLibrariesSystemConfigPathFromRoot[] = 91 "/etc/public.libraries.txt"; 92 static constexpr const char kPublicNativeLibrariesExtensionConfigPrefix[] = "public.libraries-"; 93 static constexpr const size_t kPublicNativeLibrariesExtensionConfigPrefixLen = 94 sizeof(kPublicNativeLibrariesExtensionConfigPrefix) - 1; 95 static constexpr const char kPublicNativeLibrariesExtensionConfigSuffix[] = ".txt"; 96 static constexpr const size_t kPublicNativeLibrariesExtensionConfigSuffixLen = 97 sizeof(kPublicNativeLibrariesExtensionConfigSuffix) - 1; 98 static constexpr const char kPublicNativeLibrariesVendorConfig[] = 99 "/vendor/etc/public.libraries.txt"; 100 static constexpr const char kLlndkNativeLibrariesSystemConfigPathFromRoot[] = 101 "/etc/llndk.libraries.txt"; 102 static constexpr const char kVndkspNativeLibrariesSystemConfigPathFromRoot[] = 103 "/etc/vndksp.libraries.txt"; 104 105 // The device may be configured to have the vendor libraries loaded to a separate namespace. 106 // For historical reasons this namespace was named sphal but effectively it is intended 107 // to use to load vendor libraries to separate namespace with controlled interface between 108 // vendor and system namespaces. 109 static constexpr const char* kVendorNamespaceName = "sphal"; 110 111 static constexpr const char* kVndkNamespaceName = "vndk"; 112 113 static constexpr const char* kClassloaderNamespaceName = "classloader-namespace"; 114 static constexpr const char* kVendorClassloaderNamespaceName = "vendor-classloader-namespace"; 115 116 // (http://b/27588281) This is a workaround for apps using custom classloaders and calling 117 // System.load() with an absolute path which is outside of the classloader library search path. 118 // This list includes all directories app is allowed to access this way. 119 static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand"; 120 121 static bool is_debuggable() { 122 char debuggable[PROP_VALUE_MAX]; 123 property_get("ro.debuggable", debuggable, "0"); 124 return std::string(debuggable) == "1"; 125 } 126 127 static std::string vndk_version_str() { 128 #ifdef __BIONIC__ 129 std::string version = android::base::GetProperty("ro.vndk.version", ""); 130 if (version != "" && version != "current") { 131 return "." + version; 132 } 133 #endif 134 return ""; 135 } 136 137 static void insert_vndk_version_str(std::string* file_name) { 138 CHECK(file_name != nullptr); 139 size_t insert_pos = file_name->find_last_of("."); 140 if (insert_pos == std::string::npos) { 141 insert_pos = file_name->length(); 142 } 143 file_name->insert(insert_pos, vndk_version_str()); 144 } 145 146 static const std::function<bool(const std::string&, std::string*)> always_true = 147 [](const std::string&, std::string*) { return true; }; 148 149 class LibraryNamespaces { 150 public: 151 LibraryNamespaces() : initialized_(false) { } 152 153 bool Create(JNIEnv* env, 154 uint32_t target_sdk_version, 155 jobject class_loader, 156 bool is_shared, 157 bool is_for_vendor, 158 jstring java_library_path, 159 jstring java_permitted_path, 160 NativeLoaderNamespace* ns, 161 std::string* error_msg) { 162 std::string library_path; // empty string by default. 163 164 if (java_library_path != nullptr) { 165 ScopedUtfChars library_path_utf_chars(env, java_library_path); 166 library_path = library_path_utf_chars.c_str(); 167 } 168 169 // (http://b/27588281) This is a workaround for apps using custom 170 // classloaders and calling System.load() with an absolute path which 171 // is outside of the classloader library search path. 172 // 173 // This part effectively allows such a classloader to access anything 174 // under /data and /mnt/expand 175 std::string permitted_path = kWhitelistedDirectories; 176 177 if (java_permitted_path != nullptr) { 178 ScopedUtfChars path(env, java_permitted_path); 179 if (path.c_str() != nullptr && path.size() > 0) { 180 permitted_path = permitted_path + ":" + path.c_str(); 181 } 182 } 183 184 if (!initialized_ && !InitPublicNamespace(library_path.c_str(), error_msg)) { 185 return false; 186 } 187 188 bool found = FindNamespaceByClassLoader(env, class_loader, nullptr); 189 190 LOG_ALWAYS_FATAL_IF(found, 191 "There is already a namespace associated with this classloader"); 192 193 uint64_t namespace_type = ANDROID_NAMESPACE_TYPE_ISOLATED; 194 if (is_shared) { 195 namespace_type |= ANDROID_NAMESPACE_TYPE_SHARED; 196 } 197 198 if (target_sdk_version < 24) { 199 namespace_type |= ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED; 200 } 201 202 NativeLoaderNamespace parent_ns; 203 bool found_parent_namespace = FindParentNamespaceByClassLoader(env, class_loader, &parent_ns); 204 205 bool is_native_bridge = false; 206 207 if (found_parent_namespace) { 208 is_native_bridge = !parent_ns.is_android_namespace(); 209 } else if (!library_path.empty()) { 210 is_native_bridge = NativeBridgeIsPathSupported(library_path.c_str()); 211 } 212 213 std::string system_exposed_libraries = system_public_libraries_; 214 const char* namespace_name = kClassloaderNamespaceName; 215 android_namespace_t* vndk_ns = nullptr; 216 if (is_for_vendor && !is_shared) { 217 LOG_FATAL_IF(is_native_bridge, "Unbundled vendor apk must not use translated architecture"); 218 219 // For vendor apks, give access to the vendor lib even though 220 // they are treated as unbundled; the libs and apks are still bundled 221 // together in the vendor partition. 222 #if defined(__LP64__) 223 std::string vendor_lib_path = "/vendor/lib64"; 224 #else 225 std::string vendor_lib_path = "/vendor/lib"; 226 #endif 227 library_path = library_path + ":" + vendor_lib_path.c_str(); 228 permitted_path = permitted_path + ":" + vendor_lib_path.c_str(); 229 230 // Also give access to LLNDK libraries since they are available to vendors 231 system_exposed_libraries = system_exposed_libraries + ":" + system_llndk_libraries_.c_str(); 232 233 // Give access to VNDK-SP libraries from the 'vndk' namespace. 234 vndk_ns = android_get_exported_namespace(kVndkNamespaceName); 235 LOG_ALWAYS_FATAL_IF(vndk_ns == nullptr, 236 "Cannot find \"%s\" namespace for vendor apks", kVndkNamespaceName); 237 238 // Different name is useful for debugging 239 namespace_name = kVendorClassloaderNamespaceName; 240 ALOGD("classloader namespace configured for unbundled vendor apk. library_path=%s", library_path.c_str()); 241 } else { 242 // oem and product public libraries are NOT available to vendor apks, otherwise it 243 // would be system->vendor violation. 244 if (!oem_public_libraries_.empty()) { 245 system_exposed_libraries = system_exposed_libraries + ':' + oem_public_libraries_; 246 } 247 if (!product_public_libraries_.empty()) { 248 system_exposed_libraries = system_exposed_libraries + ':' + product_public_libraries_; 249 } 250 } 251 252 NativeLoaderNamespace native_loader_ns; 253 if (!is_native_bridge) { 254 android_namespace_t* ns = android_create_namespace(namespace_name, 255 nullptr, 256 library_path.c_str(), 257 namespace_type, 258 permitted_path.c_str(), 259 parent_ns.get_android_ns()); 260 if (ns == nullptr) { 261 *error_msg = dlerror(); 262 return false; 263 } 264 265 // Note that when vendor_ns is not configured this function will return nullptr 266 // and it will result in linking vendor_public_libraries_ to the default namespace 267 // which is expected behavior in this case. 268 android_namespace_t* vendor_ns = android_get_exported_namespace(kVendorNamespaceName); 269 270 if (!android_link_namespaces(ns, nullptr, system_exposed_libraries.c_str())) { 271 *error_msg = dlerror(); 272 return false; 273 } 274 275 if (vndk_ns != nullptr && !system_vndksp_libraries_.empty()) { 276 // vendor apks are allowed to use VNDK-SP libraries. 277 if (!android_link_namespaces(ns, vndk_ns, system_vndksp_libraries_.c_str())) { 278 *error_msg = dlerror(); 279 return false; 280 } 281 } 282 283 if (!vendor_public_libraries_.empty()) { 284 if (!android_link_namespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) { 285 *error_msg = dlerror(); 286 return false; 287 } 288 } 289 290 native_loader_ns = NativeLoaderNamespace(ns); 291 } else { 292 native_bridge_namespace_t* ns = NativeBridgeCreateNamespace(namespace_name, 293 nullptr, 294 library_path.c_str(), 295 namespace_type, 296 permitted_path.c_str(), 297 parent_ns.get_native_bridge_ns()); 298 299 if (ns == nullptr) { 300 *error_msg = NativeBridgeGetError(); 301 return false; 302 } 303 304 native_bridge_namespace_t* vendor_ns = NativeBridgeGetVendorNamespace(); 305 306 if (!NativeBridgeLinkNamespaces(ns, nullptr, system_exposed_libraries.c_str())) { 307 *error_msg = NativeBridgeGetError(); 308 return false; 309 } 310 311 if (!vendor_public_libraries_.empty()) { 312 if (!NativeBridgeLinkNamespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) { 313 *error_msg = NativeBridgeGetError(); 314 return false; 315 } 316 } 317 318 native_loader_ns = NativeLoaderNamespace(ns); 319 } 320 321 namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), native_loader_ns)); 322 323 *ns = native_loader_ns; 324 return true; 325 } 326 327 bool FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader, NativeLoaderNamespace* ns) { 328 auto it = std::find_if(namespaces_.begin(), namespaces_.end(), 329 [&](const std::pair<jweak, NativeLoaderNamespace>& value) { 330 return env->IsSameObject(value.first, class_loader); 331 }); 332 if (it != namespaces_.end()) { 333 if (ns != nullptr) { 334 *ns = it->second; 335 } 336 337 return true; 338 } 339 340 return false; 341 } 342 343 void Initialize() { 344 // Once public namespace is initialized there is no 345 // point in running this code - it will have no effect 346 // on the current list of public libraries. 347 if (initialized_) { 348 return; 349 } 350 351 std::vector<std::string> sonames; 352 const char* android_root_env = getenv("ANDROID_ROOT"); 353 std::string root_dir = android_root_env != nullptr ? android_root_env : "/system"; 354 std::string public_native_libraries_system_config = 355 root_dir + kPublicNativeLibrariesSystemConfigPathFromRoot; 356 std::string llndk_native_libraries_system_config = 357 root_dir + kLlndkNativeLibrariesSystemConfigPathFromRoot; 358 std::string vndksp_native_libraries_system_config = 359 root_dir + kVndkspNativeLibrariesSystemConfigPathFromRoot; 360 361 std::string product_public_native_libraries_dir = "/product/etc"; 362 363 std::string error_msg; 364 LOG_ALWAYS_FATAL_IF( 365 !ReadConfig(public_native_libraries_system_config, &sonames, always_true, &error_msg), 366 "Error reading public native library list from \"%s\": %s", 367 public_native_libraries_system_config.c_str(), error_msg.c_str()); 368 369 // For debuggable platform builds use ANDROID_ADDITIONAL_PUBLIC_LIBRARIES environment 370 // variable to add libraries to the list. This is intended for platform tests only. 371 if (is_debuggable()) { 372 const char* additional_libs = getenv("ANDROID_ADDITIONAL_PUBLIC_LIBRARIES"); 373 if (additional_libs != nullptr && additional_libs[0] != '\0') { 374 std::vector<std::string> additional_libs_vector = base::Split(additional_libs, ":"); 375 std::copy(additional_libs_vector.begin(), additional_libs_vector.end(), 376 std::back_inserter(sonames)); 377 } 378 } 379 380 // android_init_namespaces() expects all the public libraries 381 // to be loaded so that they can be found by soname alone. 382 // 383 // TODO(dimitry): this is a bit misleading since we do not know 384 // if the vendor public library is going to be opened from /vendor/lib 385 // we might as well end up loading them from /system/lib or /product/lib 386 // For now we rely on CTS test to catch things like this but 387 // it should probably be addressed in the future. 388 for (const auto& soname : sonames) { 389 LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr, 390 "Error preloading public library %s: %s", soname.c_str(), dlerror()); 391 } 392 393 system_public_libraries_ = base::Join(sonames, ':'); 394 395 // read /system/etc/public.libraries-<companyname>.txt which contain partner defined 396 // system libs that are exposed to apps. The libs in the txt files must be 397 // named as lib<name>.<companyname>.so. 398 sonames.clear(); 399 ReadExtensionLibraries(base::Dirname(public_native_libraries_system_config).c_str(), &sonames); 400 oem_public_libraries_ = base::Join(sonames, ':'); 401 402 // read /product/etc/public.libraries-<companyname>.txt which contain partner defined 403 // product libs that are exposed to apps. 404 sonames.clear(); 405 ReadExtensionLibraries(product_public_native_libraries_dir.c_str(), &sonames); 406 product_public_libraries_ = base::Join(sonames, ':'); 407 408 // Insert VNDK version to llndk and vndksp config file names. 409 insert_vndk_version_str(&llndk_native_libraries_system_config); 410 insert_vndk_version_str(&vndksp_native_libraries_system_config); 411 412 sonames.clear(); 413 ReadConfig(llndk_native_libraries_system_config, &sonames, always_true); 414 system_llndk_libraries_ = base::Join(sonames, ':'); 415 416 sonames.clear(); 417 ReadConfig(vndksp_native_libraries_system_config, &sonames, always_true); 418 system_vndksp_libraries_ = base::Join(sonames, ':'); 419 420 sonames.clear(); 421 // This file is optional, quietly ignore if the file does not exist. 422 ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames, always_true, nullptr); 423 424 vendor_public_libraries_ = base::Join(sonames, ':'); 425 } 426 427 void Reset() { namespaces_.clear(); } 428 429 private: 430 void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonames) { 431 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dirname), closedir); 432 if (dir != nullptr) { 433 // Failing to opening the dir is not an error, which can happen in 434 // webview_zygote. 435 while (struct dirent* ent = readdir(dir.get())) { 436 if (ent->d_type != DT_REG && ent->d_type != DT_LNK) { 437 continue; 438 } 439 const std::string filename(ent->d_name); 440 if (android::base::StartsWith(filename, kPublicNativeLibrariesExtensionConfigPrefix) && 441 android::base::EndsWith(filename, kPublicNativeLibrariesExtensionConfigSuffix)) { 442 const size_t start = kPublicNativeLibrariesExtensionConfigPrefixLen; 443 const size_t end = filename.size() - kPublicNativeLibrariesExtensionConfigSuffixLen; 444 const std::string company_name = filename.substr(start, end - start); 445 const std::string config_file_path = dirname + "/"s + filename; 446 LOG_ALWAYS_FATAL_IF( 447 company_name.empty(), 448 "Error extracting company name from public native library list file path \"%s\"", 449 config_file_path.c_str()); 450 451 std::string error_msg; 452 453 LOG_ALWAYS_FATAL_IF( 454 !ReadConfig( 455 config_file_path, sonames, 456 [&company_name](const std::string& soname, std::string* error_msg) { 457 if (android::base::StartsWith(soname, "lib") && 458 android::base::EndsWith(soname, "." + company_name + ".so")) { 459 return true; 460 } else { 461 *error_msg = "Library name \"" + soname + 462 "\" does not end with the company name: " + company_name + "."; 463 return false; 464 } 465 }, 466 &error_msg), 467 "Error reading public native library list from \"%s\": %s", config_file_path.c_str(), 468 error_msg.c_str()); 469 } 470 } 471 } 472 } 473 474 475 bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames, 476 const std::function<bool(const std::string& /* soname */, 477 std::string* /* error_msg */)>& check_soname, 478 std::string* error_msg = nullptr) { 479 // Read list of public native libraries from the config file. 480 std::string file_content; 481 if(!base::ReadFileToString(configFile, &file_content)) { 482 if (error_msg) *error_msg = strerror(errno); 483 return false; 484 } 485 486 std::vector<std::string> lines = base::Split(file_content, "\n"); 487 488 for (auto& line : lines) { 489 auto trimmed_line = base::Trim(line); 490 if (trimmed_line[0] == '#' || trimmed_line.empty()) { 491 continue; 492 } 493 size_t space_pos = trimmed_line.rfind(' '); 494 if (space_pos != std::string::npos) { 495 std::string type = trimmed_line.substr(space_pos + 1); 496 if (type != "32" && type != "64") { 497 if (error_msg) *error_msg = "Malformed line: " + line; 498 return false; 499 } 500 #if defined(__LP64__) 501 // Skip 32 bit public library. 502 if (type == "32") { 503 continue; 504 } 505 #else 506 // Skip 64 bit public library. 507 if (type == "64") { 508 continue; 509 } 510 #endif 511 trimmed_line.resize(space_pos); 512 } 513 514 if (check_soname(trimmed_line, error_msg)) { 515 sonames->push_back(trimmed_line); 516 } else { 517 return false; 518 } 519 } 520 521 return true; 522 } 523 524 bool InitPublicNamespace(const char* library_path, std::string* error_msg) { 525 // Ask native bride if this apps library path should be handled by it 526 bool is_native_bridge = NativeBridgeIsPathSupported(library_path); 527 528 // (http://b/25844435) - Some apps call dlopen from generated code (mono jited 529 // code is one example) unknown to linker in which case linker uses anonymous 530 // namespace. The second argument specifies the search path for the anonymous 531 // namespace which is the library_path of the classloader. 532 initialized_ = android_init_anonymous_namespace(system_public_libraries_.c_str(), 533 is_native_bridge ? nullptr : library_path); 534 if (!initialized_) { 535 *error_msg = dlerror(); 536 return false; 537 } 538 539 // and now initialize native bridge namespaces if necessary. 540 if (NativeBridgeInitialized()) { 541 initialized_ = NativeBridgeInitAnonymousNamespace(system_public_libraries_.c_str(), 542 is_native_bridge ? library_path : nullptr); 543 if (!initialized_) { 544 *error_msg = NativeBridgeGetError(); 545 } 546 } 547 548 return initialized_; 549 } 550 551 jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) { 552 jclass class_loader_class = env->FindClass("java/lang/ClassLoader"); 553 jmethodID get_parent = env->GetMethodID(class_loader_class, 554 "getParent", 555 "()Ljava/lang/ClassLoader;"); 556 557 return env->CallObjectMethod(class_loader, get_parent); 558 } 559 560 bool FindParentNamespaceByClassLoader(JNIEnv* env, 561 jobject class_loader, 562 NativeLoaderNamespace* ns) { 563 jobject parent_class_loader = GetParentClassLoader(env, class_loader); 564 565 while (parent_class_loader != nullptr) { 566 if (FindNamespaceByClassLoader(env, parent_class_loader, ns)) { 567 return true; 568 } 569 570 parent_class_loader = GetParentClassLoader(env, parent_class_loader); 571 } 572 573 return false; 574 } 575 576 bool initialized_; 577 std::vector<std::pair<jweak, NativeLoaderNamespace>> namespaces_; 578 std::string system_public_libraries_; 579 std::string vendor_public_libraries_; 580 std::string oem_public_libraries_; 581 std::string product_public_libraries_; 582 std::string system_llndk_libraries_; 583 std::string system_vndksp_libraries_; 584 585 DISALLOW_COPY_AND_ASSIGN(LibraryNamespaces); 586 }; 587 588 static std::mutex g_namespaces_mutex; 589 static LibraryNamespaces* g_namespaces = new LibraryNamespaces; 590 #endif 591 592 void InitializeNativeLoader() { 593 #if defined(__ANDROID__) 594 std::lock_guard<std::mutex> guard(g_namespaces_mutex); 595 g_namespaces->Initialize(); 596 #endif 597 } 598 599 void ResetNativeLoader() { 600 #if defined(__ANDROID__) 601 std::lock_guard<std::mutex> guard(g_namespaces_mutex); 602 g_namespaces->Reset(); 603 #endif 604 } 605 606 jstring CreateClassLoaderNamespace(JNIEnv* env, 607 int32_t target_sdk_version, 608 jobject class_loader, 609 bool is_shared, 610 bool is_for_vendor, 611 jstring library_path, 612 jstring permitted_path) { 613 #if defined(__ANDROID__) 614 std::lock_guard<std::mutex> guard(g_namespaces_mutex); 615 616 std::string error_msg; 617 NativeLoaderNamespace ns; 618 bool success = g_namespaces->Create(env, 619 target_sdk_version, 620 class_loader, 621 is_shared, 622 is_for_vendor, 623 library_path, 624 permitted_path, 625 &ns, 626 &error_msg); 627 if (!success) { 628 return env->NewStringUTF(error_msg.c_str()); 629 } 630 #else 631 UNUSED(env, target_sdk_version, class_loader, is_shared, is_for_vendor, 632 library_path, permitted_path); 633 #endif 634 return nullptr; 635 } 636 637 void* OpenNativeLibrary(JNIEnv* env, 638 int32_t target_sdk_version, 639 const char* path, 640 jobject class_loader, 641 jstring library_path, 642 bool* needs_native_bridge, 643 std::string* error_msg) { 644 #if defined(__ANDROID__) 645 UNUSED(target_sdk_version); 646 if (class_loader == nullptr) { 647 *needs_native_bridge = false; 648 return dlopen(path, RTLD_NOW); 649 } 650 651 std::lock_guard<std::mutex> guard(g_namespaces_mutex); 652 NativeLoaderNamespace ns; 653 654 if (!g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) { 655 // This is the case where the classloader was not created by ApplicationLoaders 656 // In this case we create an isolated not-shared namespace for it. 657 if (!g_namespaces->Create(env, 658 target_sdk_version, 659 class_loader, 660 false /* is_shared */, 661 false /* is_for_vendor */, 662 library_path, 663 nullptr, 664 &ns, 665 error_msg)) { 666 return nullptr; 667 } 668 } 669 670 if (ns.is_android_namespace()) { 671 android_dlextinfo extinfo; 672 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 673 extinfo.library_namespace = ns.get_android_ns(); 674 675 void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo); 676 if (handle == nullptr) { 677 *error_msg = dlerror(); 678 } 679 *needs_native_bridge = false; 680 return handle; 681 } else { 682 void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns.get_native_bridge_ns()); 683 if (handle == nullptr) { 684 *error_msg = NativeBridgeGetError(); 685 } 686 *needs_native_bridge = true; 687 return handle; 688 } 689 #else 690 UNUSED(env, target_sdk_version, class_loader); 691 692 // Do some best effort to emulate library-path support. It will not 693 // work for dependencies. 694 // 695 // Note: null has a special meaning and must be preserved. 696 std::string c_library_path; // Empty string by default. 697 if (library_path != nullptr && path != nullptr && path[0] != '/') { 698 ScopedUtfChars library_path_utf_chars(env, library_path); 699 c_library_path = library_path_utf_chars.c_str(); 700 } 701 702 std::vector<std::string> library_paths = base::Split(c_library_path, ":"); 703 704 for (const std::string& lib_path : library_paths) { 705 *needs_native_bridge = false; 706 const char* path_arg; 707 std::string complete_path; 708 if (path == nullptr) { 709 // Preserve null. 710 path_arg = nullptr; 711 } else { 712 complete_path = lib_path; 713 if (!complete_path.empty()) { 714 complete_path.append("/"); 715 } 716 complete_path.append(path); 717 path_arg = complete_path.c_str(); 718 } 719 void* handle = dlopen(path_arg, RTLD_NOW); 720 if (handle != nullptr) { 721 return handle; 722 } 723 if (NativeBridgeIsSupported(path_arg)) { 724 *needs_native_bridge = true; 725 handle = NativeBridgeLoadLibrary(path_arg, RTLD_NOW); 726 if (handle != nullptr) { 727 return handle; 728 } 729 *error_msg = NativeBridgeGetError(); 730 } else { 731 *error_msg = dlerror(); 732 } 733 } 734 return nullptr; 735 #endif 736 } 737 738 bool CloseNativeLibrary(void* handle, const bool needs_native_bridge) { 739 return needs_native_bridge ? NativeBridgeUnloadLibrary(handle) : 740 dlclose(handle); 741 } 742 743 #if defined(__ANDROID__) 744 // native_bridge_namespaces are not supported for callers of this function. 745 // This function will return nullptr in the case when application is running 746 // on native bridge. 747 android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) { 748 std::lock_guard<std::mutex> guard(g_namespaces_mutex); 749 NativeLoaderNamespace ns; 750 if (g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) { 751 return ns.is_android_namespace() ? ns.get_android_ns() : nullptr; 752 } 753 754 return nullptr; 755 } 756 #endif 757 758 }; // android namespace 759