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 "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:
     47   NativeLoaderNamespace()
     48       : android_ns_(nullptr), native_bridge_ns_(nullptr) { }
     49 
     50   explicit NativeLoaderNamespace(android_namespace_t* ns)
     51       : android_ns_(ns), native_bridge_ns_(nullptr) { }
     52 
     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 
     61   android_namespace_t* get_android_ns() const {
     62     CHECK(native_bridge_ns_ == nullptr);
     63     return android_ns_;
     64   }
     65 
     66   native_bridge_namespace_t* get_native_bridge_ns() const {
     67     CHECK(android_ns_ == nullptr);
     68     return native_bridge_ns_;
     69   }
     70 
     71   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 
     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:
    105   LibraryNamespaces() : initialized_(false) { }
    106 
    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 
    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 
    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 
    303   void Reset() {
    304     namespaces_.clear();
    305   }
    306 
    307  private:
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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.
    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