• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
NativeLoaderNamespace()56   NativeLoaderNamespace()
57       : android_ns_(nullptr), native_bridge_ns_(nullptr) { }
58 
NativeLoaderNamespace(android_namespace_t * ns)59   explicit NativeLoaderNamespace(android_namespace_t* ns)
60       : android_ns_(ns), native_bridge_ns_(nullptr) { }
61 
NativeLoaderNamespace(native_bridge_namespace_t * ns)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 
get_android_ns() const70   android_namespace_t* get_android_ns() const {
71     CHECK(native_bridge_ns_ == nullptr);
72     return android_ns_;
73   }
74 
get_native_bridge_ns() const75   native_bridge_namespace_t* get_native_bridge_ns() const {
76     CHECK(android_ns_ == nullptr);
77     return native_bridge_ns_;
78   }
79 
is_android_namespace() const80   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 
is_debuggable()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 
vndk_version_str()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 
insert_vndk_version_str(std::string * file_name)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 =
__anon341ec5ba0102(const std::string&, std::string*) 147     [](const std::string&, std::string*) { return true; };
148 
149 class LibraryNamespaces {
150  public:
LibraryNamespaces()151   LibraryNamespaces() : initialized_(false) { }
152 
Create(JNIEnv * env,uint32_t target_sdk_version,jobject class_loader,bool is_shared,bool is_for_vendor,jstring java_library_path,jstring java_permitted_path,NativeLoaderNamespace * ns,std::string * error_msg)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 
FindNamespaceByClassLoader(JNIEnv * env,jobject class_loader,NativeLoaderNamespace * ns)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 
Initialize()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 
Reset()427   void Reset() { namespaces_.clear(); }
428 
429  private:
ReadExtensionLibraries(const char * dirname,std::vector<std::string> * sonames)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 
ReadConfig(const std::string & configFile,std::vector<std::string> * sonames,const std::function<bool (const std::string &,std::string *)> & check_soname,std::string * error_msg=nullptr)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 
InitPublicNamespace(const char * library_path,std::string * error_msg)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 
GetParentClassLoader(JNIEnv * env,jobject class_loader)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 
FindParentNamespaceByClassLoader(JNIEnv * env,jobject class_loader,NativeLoaderNamespace * ns)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 
InitializeNativeLoader()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 
ResetNativeLoader()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 
CreateClassLoaderNamespace(JNIEnv * env,int32_t target_sdk_version,jobject class_loader,bool is_shared,bool is_for_vendor,jstring library_path,jstring permitted_path)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 
OpenNativeLibrary(JNIEnv * env,int32_t target_sdk_version,const char * path,jobject class_loader,jstring library_path,bool * needs_native_bridge,std::string * error_msg)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 
CloseNativeLibrary(void * handle,const bool needs_native_bridge)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.
FindNamespaceByClassLoader(JNIEnv * env,jobject class_loader)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