Home | History | Annotate | Download | only in libnativeloader
      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