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 #define LOG_TAG "nativeloader"
18 
19 #include "nativeloader/native_loader.h"
20 
21 #include <dlfcn.h>
22 #include <sys/types.h>
23 
24 #include <algorithm>
25 #include <memory>
26 #include <mutex>
27 #include <string>
28 #include <vector>
29 
30 #include <android-base/file.h>
31 #include <android-base/macros.h>
32 #include <android-base/strings.h>
33 #include <nativebridge/native_bridge.h>
34 #include <nativehelper/scoped_utf_chars.h>
35 
36 #ifdef ART_TARGET_ANDROID
37 #include <log/log.h>
38 #include "library_namespaces.h"
39 #include "nativeloader/dlext_namespaces.h"
40 #endif
41 
42 namespace android {
43 
44 namespace {
45 #if defined(ART_TARGET_ANDROID)
46 using android::nativeloader::LibraryNamespaces;
47 
48 std::mutex g_namespaces_mutex;
49 LibraryNamespaces* g_namespaces = new LibraryNamespaces;
50 
FindExportedNamespace(const char * caller_location)51 android_namespace_t* FindExportedNamespace(const char* caller_location) {
52   auto name = nativeloader::FindApexNamespaceName(caller_location);
53   if (name.ok()) {
54     android_namespace_t* boot_namespace = android_get_exported_namespace(name->c_str());
55     LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr),
56                         "Error finding namespace of apex: no namespace called %s", name->c_str());
57     return boot_namespace;
58   }
59   return nullptr;
60 }
61 #endif  // #if defined(ART_TARGET_ANDROID)
62 }  // namespace
63 
InitializeNativeLoader()64 void InitializeNativeLoader() {
65 #if defined(ART_TARGET_ANDROID)
66   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
67   g_namespaces->Initialize();
68 #endif
69 }
70 
ResetNativeLoader()71 void ResetNativeLoader() {
72 #if defined(ART_TARGET_ANDROID)
73   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
74   g_namespaces->Reset();
75 #endif
76 }
77 
CreateClassLoaderNamespace(JNIEnv * env,int32_t target_sdk_version,jobject class_loader,bool is_shared,jstring dex_path,jstring library_path,jstring permitted_path,jstring uses_library_list)78 jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
79                                    bool is_shared, jstring dex_path, jstring library_path,
80                                    jstring permitted_path, jstring uses_library_list) {
81 #if defined(ART_TARGET_ANDROID)
82   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
83   auto ns = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
84                                  library_path, permitted_path, uses_library_list);
85   if (!ns.ok()) {
86     return env->NewStringUTF(ns.error().message().c_str());
87   }
88 #else
89   UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path,
90          uses_library_list);
91 #endif
92   return nullptr;
93 }
94 
OpenNativeLibrary(JNIEnv * env,int32_t target_sdk_version,const char * path,jobject class_loader,const char * caller_location,jstring library_path,bool * needs_native_bridge,char ** error_msg)95 void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
96                         jobject class_loader, const char* caller_location, jstring library_path,
97                         bool* needs_native_bridge, char** error_msg) {
98 #if defined(ART_TARGET_ANDROID)
99   UNUSED(target_sdk_version);
100   if (class_loader == nullptr) {
101     *needs_native_bridge = false;
102     if (caller_location != nullptr) {
103       android_namespace_t* boot_namespace = FindExportedNamespace(caller_location);
104       if (boot_namespace != nullptr) {
105         const android_dlextinfo dlextinfo = {
106             .flags = ANDROID_DLEXT_USE_NAMESPACE,
107             .library_namespace = boot_namespace,
108         };
109         void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo);
110         if (handle == nullptr) {
111           *error_msg = strdup(dlerror());
112         }
113         return handle;
114       }
115     }
116     void* handle = dlopen(path, RTLD_NOW);
117     if (handle == nullptr) {
118       *error_msg = strdup(dlerror());
119     }
120     return handle;
121   }
122 
123   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
124   NativeLoaderNamespace* ns;
125 
126   if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
127     // This is the case where the classloader was not created by ApplicationLoaders
128     // In this case we create an isolated not-shared namespace for it.
129     Result<NativeLoaderNamespace*> isolated_ns =
130         g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */, nullptr,
131                              library_path, nullptr, nullptr);
132     if (!isolated_ns.ok()) {
133       *error_msg = strdup(isolated_ns.error().message().c_str());
134       return nullptr;
135     } else {
136       ns = *isolated_ns;
137     }
138   }
139 
140   return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
141 #else
142   UNUSED(env, target_sdk_version, class_loader, caller_location);
143 
144   // Do some best effort to emulate library-path support. It will not
145   // work for dependencies.
146   //
147   // Note: null has a special meaning and must be preserved.
148   std::string c_library_path;  // Empty string by default.
149   if (library_path != nullptr && path != nullptr && path[0] != '/') {
150     ScopedUtfChars library_path_utf_chars(env, library_path);
151     c_library_path = library_path_utf_chars.c_str();
152   }
153 
154   std::vector<std::string> library_paths = base::Split(c_library_path, ":");
155 
156   for (const std::string& lib_path : library_paths) {
157     *needs_native_bridge = false;
158     const char* path_arg;
159     std::string complete_path;
160     if (path == nullptr) {
161       // Preserve null.
162       path_arg = nullptr;
163     } else {
164       complete_path = lib_path;
165       if (!complete_path.empty()) {
166         complete_path.append("/");
167       }
168       complete_path.append(path);
169       path_arg = complete_path.c_str();
170     }
171     void* handle = dlopen(path_arg, RTLD_NOW);
172     if (handle != nullptr) {
173       return handle;
174     }
175     if (NativeBridgeIsSupported(path_arg)) {
176       *needs_native_bridge = true;
177       handle = NativeBridgeLoadLibrary(path_arg, RTLD_NOW);
178       if (handle != nullptr) {
179         return handle;
180       }
181       *error_msg = strdup(NativeBridgeGetError());
182     } else {
183       *error_msg = strdup(dlerror());
184     }
185   }
186   return nullptr;
187 #endif
188 }
189 
CloseNativeLibrary(void * handle,const bool needs_native_bridge,char ** error_msg)190 bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
191   bool success;
192   if (needs_native_bridge) {
193     success = (NativeBridgeUnloadLibrary(handle) == 0);
194     if (!success) {
195       *error_msg = strdup(NativeBridgeGetError());
196     }
197   } else {
198     success = (dlclose(handle) == 0);
199     if (!success) {
200       *error_msg = strdup(dlerror());
201     }
202   }
203 
204   return success;
205 }
206 
NativeLoaderFreeErrorMessage(char * msg)207 void NativeLoaderFreeErrorMessage(char* msg) {
208   // The error messages get allocated through strdup, so we must call free on them.
209   free(msg);
210 }
211 
212 #if defined(ART_TARGET_ANDROID)
OpenNativeLibraryInNamespace(NativeLoaderNamespace * ns,const char * path,bool * needs_native_bridge,char ** error_msg)213 void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
214                                    bool* needs_native_bridge, char** error_msg) {
215   auto handle = ns->Load(path);
216   if (!handle.ok() && error_msg != nullptr) {
217     *error_msg = strdup(handle.error().message().c_str());
218   }
219   if (needs_native_bridge != nullptr) {
220     *needs_native_bridge = ns->IsBridged();
221   }
222   return handle.ok() ? *handle : nullptr;
223 }
224 
225 // native_bridge_namespaces are not supported for callers of this function.
226 // This function will return nullptr in the case when application is running
227 // on native bridge.
FindNamespaceByClassLoader(JNIEnv * env,jobject class_loader)228 android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
229   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
230   NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader);
231   if (ns != nullptr && !ns->IsBridged()) {
232     return ns->ToRawAndroidNamespace();
233   }
234   return nullptr;
235 }
236 
FindNativeLoaderNamespaceByClassLoader(JNIEnv * env,jobject class_loader)237 NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
238   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
239   return g_namespaces->FindNamespaceByClassLoader(env, class_loader);
240 }
241 #endif
242 
243 };  // namespace android
244