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