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