• 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 "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 "nativebridge/native_bridge.h"
28 
29 #include <algorithm>
30 #include <vector>
31 #include <string>
32 #include <mutex>
33 
34 #include <android-base/file.h>
35 #include <android-base/macros.h>
36 #include <android-base/strings.h>
37 
38 #define CHECK(predicate) LOG_ALWAYS_FATAL_IF(!(predicate),\
39                                              "%s:%d: %s CHECK '" #predicate "' failed.",\
40                                              __FILE__, __LINE__, __FUNCTION__)
41 
42 namespace android {
43 
44 #if defined(__ANDROID__)
45 class NativeLoaderNamespace {
46  public:
NativeLoaderNamespace()47   NativeLoaderNamespace()
48       : android_ns_(nullptr), native_bridge_ns_(nullptr) { }
49 
NativeLoaderNamespace(android_namespace_t * ns)50   explicit NativeLoaderNamespace(android_namespace_t* ns)
51       : android_ns_(ns), native_bridge_ns_(nullptr) { }
52 
NativeLoaderNamespace(native_bridge_namespace_t * ns)53   explicit NativeLoaderNamespace(native_bridge_namespace_t* ns)
54       : android_ns_(nullptr), native_bridge_ns_(ns) { }
55 
56   NativeLoaderNamespace(NativeLoaderNamespace&& that) = default;
57   NativeLoaderNamespace(const NativeLoaderNamespace& that) = default;
58 
59   NativeLoaderNamespace& operator=(const NativeLoaderNamespace& that) = default;
60 
get_android_ns() const61   android_namespace_t* get_android_ns() const {
62     CHECK(native_bridge_ns_ == nullptr);
63     return android_ns_;
64   }
65 
get_native_bridge_ns() const66   native_bridge_namespace_t* get_native_bridge_ns() const {
67     CHECK(android_ns_ == nullptr);
68     return native_bridge_ns_;
69   }
70 
is_android_namespace() const71   bool is_android_namespace() const {
72     return native_bridge_ns_ == nullptr;
73   }
74 
75  private:
76   // Only one of them can be not null
77   android_namespace_t* android_ns_;
78   native_bridge_namespace_t* native_bridge_ns_;
79 };
80 
81 static constexpr const char* kPublicNativeLibrariesSystemConfigPathFromRoot =
82                                   "/etc/public.libraries.txt";
83 static constexpr const char* kPublicNativeLibrariesVendorConfig =
84                                   "/vendor/etc/public.libraries.txt";
85 
86 // The device may be configured to have the vendor libraries loaded to a separate namespace.
87 // For historical reasons this namespace was named sphal but effectively it is intended
88 // to use to load vendor libraries to separate namespace with controlled interface between
89 // vendor and system namespaces.
90 static constexpr const char* kVendorNamespaceName = "sphal";
91 
92 // (http://b/27588281) This is a workaround for apps using custom classloaders and calling
93 // System.load() with an absolute path which is outside of the classloader library search path.
94 // This list includes all directories app is allowed to access this way.
95 static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand";
96 
is_debuggable()97 static bool is_debuggable() {
98   char debuggable[PROP_VALUE_MAX];
99   property_get("ro.debuggable", debuggable, "0");
100   return std::string(debuggable) == "1";
101 }
102 
103 class LibraryNamespaces {
104  public:
LibraryNamespaces()105   LibraryNamespaces() : initialized_(false) { }
106 
Create(JNIEnv * env,uint32_t target_sdk_version,jobject class_loader,bool is_shared,jstring java_library_path,jstring java_permitted_path,NativeLoaderNamespace * ns,std::string * error_msg)107   bool Create(JNIEnv* env,
108               uint32_t target_sdk_version,
109               jobject class_loader,
110               bool is_shared,
111               jstring java_library_path,
112               jstring java_permitted_path,
113               NativeLoaderNamespace* ns,
114               std::string* error_msg) {
115     std::string library_path; // empty string by default.
116 
117     if (java_library_path != nullptr) {
118       ScopedUtfChars library_path_utf_chars(env, java_library_path);
119       library_path = library_path_utf_chars.c_str();
120     }
121 
122     // (http://b/27588281) This is a workaround for apps using custom
123     // classloaders and calling System.load() with an absolute path which
124     // is outside of the classloader library search path.
125     //
126     // This part effectively allows such a classloader to access anything
127     // under /data and /mnt/expand
128     std::string permitted_path = kWhitelistedDirectories;
129 
130     if (java_permitted_path != nullptr) {
131       ScopedUtfChars path(env, java_permitted_path);
132       if (path.c_str() != nullptr && path.size() > 0) {
133         permitted_path = permitted_path + ":" + path.c_str();
134       }
135     }
136 
137     if (!initialized_ && !InitPublicNamespace(library_path.c_str(), error_msg)) {
138       return false;
139     }
140 
141     bool found = FindNamespaceByClassLoader(env, class_loader, nullptr);
142 
143     LOG_ALWAYS_FATAL_IF(found,
144                         "There is already a namespace associated with this classloader");
145 
146     uint64_t namespace_type = ANDROID_NAMESPACE_TYPE_ISOLATED;
147     if (is_shared) {
148       namespace_type |= ANDROID_NAMESPACE_TYPE_SHARED;
149     }
150 
151     if (target_sdk_version < 24) {
152       namespace_type |= ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED;
153     }
154 
155     NativeLoaderNamespace parent_ns;
156     bool found_parent_namespace = FindParentNamespaceByClassLoader(env, class_loader, &parent_ns);
157 
158     bool is_native_bridge = false;
159 
160     if (found_parent_namespace) {
161       is_native_bridge = !parent_ns.is_android_namespace();
162     } else if (!library_path.empty()) {
163       is_native_bridge = NativeBridgeIsPathSupported(library_path.c_str());
164     }
165 
166     NativeLoaderNamespace native_loader_ns;
167     if (!is_native_bridge) {
168       android_namespace_t* ns = android_create_namespace("classloader-namespace",
169                                                          nullptr,
170                                                          library_path.c_str(),
171                                                          namespace_type,
172                                                          permitted_path.c_str(),
173                                                          parent_ns.get_android_ns());
174       if (ns == nullptr) {
175         *error_msg = dlerror();
176         return false;
177       }
178 
179       // Note that when vendor_ns is not configured this function will return nullptr
180       // and it will result in linking vendor_public_libraries_ to the default namespace
181       // which is expected behavior in this case.
182       android_namespace_t* vendor_ns = android_get_exported_namespace(kVendorNamespaceName);
183 
184       if (!android_link_namespaces(ns, nullptr, system_public_libraries_.c_str())) {
185         *error_msg = dlerror();
186         return false;
187       }
188 
189       if (!vendor_public_libraries_.empty()) {
190         if (!android_link_namespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
191           *error_msg = dlerror();
192           return false;
193         }
194       }
195 
196       native_loader_ns = NativeLoaderNamespace(ns);
197     } else {
198       native_bridge_namespace_t* ns = NativeBridgeCreateNamespace("classloader-namespace",
199                                                                   nullptr,
200                                                                   library_path.c_str(),
201                                                                   namespace_type,
202                                                                   permitted_path.c_str(),
203                                                                   parent_ns.get_native_bridge_ns());
204 
205       if (ns == nullptr) {
206         *error_msg = NativeBridgeGetError();
207         return false;
208       }
209 
210       native_bridge_namespace_t* vendor_ns = NativeBridgeGetVendorNamespace();
211 
212       if (!NativeBridgeLinkNamespaces(ns, nullptr, system_public_libraries_.c_str())) {
213         *error_msg = NativeBridgeGetError();
214         return false;
215       }
216 
217       if (!vendor_public_libraries_.empty()) {
218         if (!NativeBridgeLinkNamespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
219           *error_msg = NativeBridgeGetError();
220           return false;
221         }
222       }
223 
224       native_loader_ns = NativeLoaderNamespace(ns);
225     }
226 
227     namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), native_loader_ns));
228 
229     *ns = native_loader_ns;
230     return true;
231   }
232 
FindNamespaceByClassLoader(JNIEnv * env,jobject class_loader,NativeLoaderNamespace * ns)233   bool FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader, NativeLoaderNamespace* ns) {
234     auto it = std::find_if(namespaces_.begin(), namespaces_.end(),
235                 [&](const std::pair<jweak, NativeLoaderNamespace>& value) {
236                   return env->IsSameObject(value.first, class_loader);
237                 });
238     if (it != namespaces_.end()) {
239       if (ns != nullptr) {
240         *ns = it->second;
241       }
242 
243       return true;
244     }
245 
246     return false;
247   }
248 
Initialize()249   void Initialize() {
250     // Once public namespace is initialized there is no
251     // point in running this code - it will have no effect
252     // on the current list of public libraries.
253     if (initialized_) {
254       return;
255     }
256 
257     std::vector<std::string> sonames;
258     const char* android_root_env = getenv("ANDROID_ROOT");
259     std::string root_dir = android_root_env != nullptr ? android_root_env : "/system";
260     std::string public_native_libraries_system_config =
261             root_dir + kPublicNativeLibrariesSystemConfigPathFromRoot;
262 
263     std::string error_msg;
264     LOG_ALWAYS_FATAL_IF(!ReadConfig(public_native_libraries_system_config, &sonames, &error_msg),
265                         "Error reading public native library list from \"%s\": %s",
266                         public_native_libraries_system_config.c_str(), error_msg.c_str());
267 
268     // For debuggable platform builds use ANDROID_ADDITIONAL_PUBLIC_LIBRARIES environment
269     // variable to add libraries to the list. This is intended for platform tests only.
270     if (is_debuggable()) {
271       const char* additional_libs = getenv("ANDROID_ADDITIONAL_PUBLIC_LIBRARIES");
272       if (additional_libs != nullptr && additional_libs[0] != '\0') {
273         std::vector<std::string> additional_libs_vector = base::Split(additional_libs, ":");
274         std::copy(additional_libs_vector.begin(),
275                   additional_libs_vector.end(),
276                   std::back_inserter(sonames));
277       }
278     }
279 
280     // android_init_namespaces() expects all the public libraries
281     // to be loaded so that they can be found by soname alone.
282     //
283     // TODO(dimitry): this is a bit misleading since we do not know
284     // if the vendor public library is going to be opened from /vendor/lib
285     // we might as well end up loading them from /system/lib
286     // For now we rely on CTS test to catch things like this but
287     // it should probably be addressed in the future.
288     for (const auto& soname : sonames) {
289       LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr,
290                           "Error preloading public library %s: %s",
291                           soname.c_str(), dlerror());
292     }
293 
294     system_public_libraries_ = base::Join(sonames, ':');
295 
296     sonames.clear();
297     // This file is optional, quietly ignore if the file does not exist.
298     ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames);
299 
300     vendor_public_libraries_ = base::Join(sonames, ':');
301   }
302 
Reset()303   void Reset() {
304     namespaces_.clear();
305   }
306 
307  private:
ReadConfig(const std::string & configFile,std::vector<std::string> * sonames,std::string * error_msg=nullptr)308   bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames,
309                   std::string* error_msg = nullptr) {
310     // Read list of public native libraries from the config file.
311     std::string file_content;
312     if(!base::ReadFileToString(configFile, &file_content)) {
313       if (error_msg) *error_msg = strerror(errno);
314       return false;
315     }
316 
317     std::vector<std::string> lines = base::Split(file_content, "\n");
318 
319     for (auto& line : lines) {
320       auto trimmed_line = base::Trim(line);
321       if (trimmed_line[0] == '#' || trimmed_line.empty()) {
322         continue;
323       }
324       size_t space_pos = trimmed_line.rfind(' ');
325       if (space_pos != std::string::npos) {
326         std::string type = trimmed_line.substr(space_pos + 1);
327         if (type != "32" && type != "64") {
328           if (error_msg) *error_msg = "Malformed line: " + line;
329           return false;
330         }
331 #if defined(__LP64__)
332         // Skip 32 bit public library.
333         if (type == "32") {
334           continue;
335         }
336 #else
337         // Skip 64 bit public library.
338         if (type == "64") {
339           continue;
340         }
341 #endif
342         trimmed_line.resize(space_pos);
343       }
344 
345       sonames->push_back(trimmed_line);
346     }
347 
348     return true;
349   }
350 
InitPublicNamespace(const char * library_path,std::string * error_msg)351   bool InitPublicNamespace(const char* library_path, std::string* error_msg) {
352     // Ask native bride if this apps library path should be handled by it
353     bool is_native_bridge = NativeBridgeIsPathSupported(library_path);
354 
355     // (http://b/25844435) - Some apps call dlopen from generated code (mono jited
356     // code is one example) unknown to linker in which  case linker uses anonymous
357     // namespace. The second argument specifies the search path for the anonymous
358     // namespace which is the library_path of the classloader.
359     initialized_ = android_init_anonymous_namespace(system_public_libraries_.c_str(),
360                                                     is_native_bridge ? nullptr : library_path);
361     if (!initialized_) {
362       *error_msg = dlerror();
363       return false;
364     }
365 
366     // and now initialize native bridge namespaces if necessary.
367     if (NativeBridgeInitialized()) {
368       initialized_ = NativeBridgeInitAnonymousNamespace(system_public_libraries_.c_str(),
369                                                         is_native_bridge ? library_path : nullptr);
370       if (!initialized_) {
371         *error_msg = NativeBridgeGetError();
372       }
373     }
374 
375     return initialized_;
376   }
377 
GetParentClassLoader(JNIEnv * env,jobject class_loader)378   jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) {
379     jclass class_loader_class = env->FindClass("java/lang/ClassLoader");
380     jmethodID get_parent = env->GetMethodID(class_loader_class,
381                                             "getParent",
382                                             "()Ljava/lang/ClassLoader;");
383 
384     return env->CallObjectMethod(class_loader, get_parent);
385   }
386 
FindParentNamespaceByClassLoader(JNIEnv * env,jobject class_loader,NativeLoaderNamespace * ns)387   bool FindParentNamespaceByClassLoader(JNIEnv* env,
388                                         jobject class_loader,
389                                         NativeLoaderNamespace* ns) {
390     jobject parent_class_loader = GetParentClassLoader(env, class_loader);
391 
392     while (parent_class_loader != nullptr) {
393       if (FindNamespaceByClassLoader(env, parent_class_loader, ns)) {
394         return true;
395       }
396 
397       parent_class_loader = GetParentClassLoader(env, parent_class_loader);
398     }
399 
400     return false;
401   }
402 
403   bool initialized_;
404   std::vector<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
405   std::string system_public_libraries_;
406   std::string vendor_public_libraries_;
407 
408   DISALLOW_COPY_AND_ASSIGN(LibraryNamespaces);
409 };
410 
411 static std::mutex g_namespaces_mutex;
412 static LibraryNamespaces* g_namespaces = new LibraryNamespaces;
413 #endif
414 
InitializeNativeLoader()415 void InitializeNativeLoader() {
416 #if defined(__ANDROID__)
417   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
418   g_namespaces->Initialize();
419 #endif
420 }
421 
ResetNativeLoader()422 void ResetNativeLoader() {
423 #if defined(__ANDROID__)
424   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
425   g_namespaces->Reset();
426 #endif
427 }
428 
CreateClassLoaderNamespace(JNIEnv * env,int32_t target_sdk_version,jobject class_loader,bool is_shared,jstring library_path,jstring permitted_path)429 jstring CreateClassLoaderNamespace(JNIEnv* env,
430                                    int32_t target_sdk_version,
431                                    jobject class_loader,
432                                    bool is_shared,
433                                    jstring library_path,
434                                    jstring permitted_path) {
435 #if defined(__ANDROID__)
436   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
437 
438   std::string error_msg;
439   NativeLoaderNamespace ns;
440   bool success = g_namespaces->Create(env,
441                                       target_sdk_version,
442                                       class_loader,
443                                       is_shared,
444                                       library_path,
445                                       permitted_path,
446                                       &ns,
447                                       &error_msg);
448   if (!success) {
449     return env->NewStringUTF(error_msg.c_str());
450   }
451 #else
452   UNUSED(env, target_sdk_version, class_loader, is_shared,
453          library_path, permitted_path);
454 #endif
455   return nullptr;
456 }
457 
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)458 void* OpenNativeLibrary(JNIEnv* env,
459                         int32_t target_sdk_version,
460                         const char* path,
461                         jobject class_loader,
462                         jstring library_path,
463                         bool* needs_native_bridge,
464                         std::string* error_msg) {
465 #if defined(__ANDROID__)
466   UNUSED(target_sdk_version);
467   if (class_loader == nullptr) {
468     *needs_native_bridge = false;
469     return dlopen(path, RTLD_NOW);
470   }
471 
472   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
473   NativeLoaderNamespace ns;
474 
475   if (!g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) {
476     // This is the case where the classloader was not created by ApplicationLoaders
477     // In this case we create an isolated not-shared namespace for it.
478     if (!g_namespaces->Create(env,
479                               target_sdk_version,
480                               class_loader,
481                               false,
482                               library_path,
483                               nullptr,
484                               &ns,
485                               error_msg)) {
486       return nullptr;
487     }
488   }
489 
490   if (ns.is_android_namespace()) {
491     android_dlextinfo extinfo;
492     extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
493     extinfo.library_namespace = ns.get_android_ns();
494 
495     void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo);
496     if (handle == nullptr) {
497       *error_msg = dlerror();
498     }
499     *needs_native_bridge = false;
500     return handle;
501   } else {
502     void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns.get_native_bridge_ns());
503     if (handle == nullptr) {
504       *error_msg = NativeBridgeGetError();
505     }
506     *needs_native_bridge = true;
507     return handle;
508   }
509 #else
510   UNUSED(env, target_sdk_version, class_loader, library_path);
511   *needs_native_bridge = false;
512   void* handle = dlopen(path, RTLD_NOW);
513   if (handle == nullptr) {
514     if (NativeBridgeIsSupported(path)) {
515       *needs_native_bridge = true;
516       handle = NativeBridgeLoadLibrary(path, RTLD_NOW);
517       if (handle == nullptr) {
518         *error_msg = NativeBridgeGetError();
519       }
520     } else {
521       *needs_native_bridge = false;
522       *error_msg = dlerror();
523     }
524   }
525   return handle;
526 #endif
527 }
528 
CloseNativeLibrary(void * handle,const bool needs_native_bridge)529 bool CloseNativeLibrary(void* handle, const bool needs_native_bridge) {
530     return needs_native_bridge ? NativeBridgeUnloadLibrary(handle) :
531                                  dlclose(handle);
532 }
533 
534 #if defined(__ANDROID__)
535 // native_bridge_namespaces are not supported for callers of this function.
536 // This function will return nullptr in the case when application is running
537 // on native bridge.
FindNamespaceByClassLoader(JNIEnv * env,jobject class_loader)538 android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
539   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
540   NativeLoaderNamespace ns;
541   if (g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) {
542     return ns.is_android_namespace() ? ns.get_android_ns() : nullptr;
543   }
544 
545   return nullptr;
546 }
547 #endif
548 
549 }; //  android namespace
550