blob: b34692ae16d5009c1e8f934b989c486da3840c87 [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>
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010032#include <android-base/properties.h>
Orion Hodson9b16e342019-10-09 13:29:16 +010033#include <android-base/strings.h>
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010034#include <android-base/thread_annotations.h>
Orion Hodson9b16e342019-10-09 13:29:16 +010035#include <nativebridge/native_bridge.h>
Orion Hodson6dc0a432020-02-06 14:28:28 +000036#include <nativehelper/scoped_utf_chars.h>
Orion Hodson9b16e342019-10-09 13:29:16 +010037
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +010038#ifdef ART_TARGET_ANDROID
Orion Hodson9b16e342019-10-09 13:29:16 +010039#include <log/log.h>
40#include "library_namespaces.h"
41#include "nativeloader/dlext_namespaces.h"
42#endif
43
44namespace android {
45
46namespace {
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010047
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +010048#if defined(ART_TARGET_ANDROID)
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010049
50// NATIVELOADER_DEFAULT_NAMESPACE_LIBS is an environment variable that can be
51// used when ro.debuggable is true to list extra libraries (separated by ":")
52// that libnativeloader will load from the default namespace. The libraries must
53// be listed without paths, and then LD_LIBRARY_PATH is typically set to the
54// directories to load them from. The libraries will be available in all
55// classloader namespaces, and also in the fallback namespace used when no
56// classloader is given.
57//
58// kNativeloaderExtraLibs is the name of that fallback namespace.
59//
60// NATIVELOADER_DEFAULT_NAMESPACE_LIBS is intended to be used for testing only,
61// and in particular in the ART run tests that are executed through dalvikvm in
62// the APEX. In that case the default namespace links to the ART namespace
63// (com_android_art) for all libraries, which means this can be used to load
64// test libraries that depend on ART internal libraries.
65constexpr const char* kNativeloaderExtraLibs = "nativeloader-extra-libs";
66
67bool Debuggable() {
68 static bool debuggable = android::base::GetBoolProperty("ro.debuggable", false);
69 return debuggable;
70}
71
Orion Hodson9b16e342019-10-09 13:29:16 +010072using android::nativeloader::LibraryNamespaces;
73
Orion Hodson9b16e342019-10-09 13:29:16 +010074std::mutex g_namespaces_mutex;
75LibraryNamespaces* g_namespaces = new LibraryNamespaces;
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010076NativeLoaderNamespace* g_nativeloader_extra_libs_namespace = nullptr;
Orion Hodson9b16e342019-10-09 13:29:16 +010077
78android_namespace_t* FindExportedNamespace(const char* caller_location) {
Jooyung Han538f99a2020-03-03 00:46:50 +090079 auto name = nativeloader::FindApexNamespaceName(caller_location);
80 if (name.ok()) {
81 android_namespace_t* boot_namespace = android_get_exported_namespace(name->c_str());
Orion Hodson9b16e342019-10-09 13:29:16 +010082 LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr),
Jooyung Han538f99a2020-03-03 00:46:50 +090083 "Error finding namespace of apex: no namespace called %s", name->c_str());
Orion Hodson9b16e342019-10-09 13:29:16 +010084 return boot_namespace;
85 }
86 return nullptr;
87}
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010088
89Result<void> CreateNativeloaderDefaultNamespaceLibsLink(NativeLoaderNamespace& ns)
90 REQUIRES(g_namespaces_mutex) {
91 const char* links = getenv("NATIVELOADER_DEFAULT_NAMESPACE_LIBS");
92 if (links == nullptr || *links == 0) {
93 return {};
94 }
95 // Pass nullptr to Link() to create a link to the default namespace without
96 // requiring it to be visible.
97 return ns.Link(nullptr, links);
98}
99
100Result<NativeLoaderNamespace*> GetNativeloaderExtraLibsNamespace() REQUIRES(g_namespaces_mutex) {
101 if (g_nativeloader_extra_libs_namespace != nullptr) {
102 return g_nativeloader_extra_libs_namespace;
103 }
104
105 Result<NativeLoaderNamespace> ns =
106 NativeLoaderNamespace::Create(kNativeloaderExtraLibs,
107 /*search_paths=*/"",
108 /*permitted_paths=*/"",
109 /*parent=*/nullptr,
110 /*is_shared=*/false,
111 /*is_exempt_list_enabled=*/false,
112 /*also_used_as_anonymous=*/false);
113 if (!ns.ok()) {
114 return ns.error();
115 }
116 g_nativeloader_extra_libs_namespace = new NativeLoaderNamespace(std::move(ns.value()));
117 Result<void> linked =
118 CreateNativeloaderDefaultNamespaceLibsLink(*g_nativeloader_extra_libs_namespace);
119 if (!linked.ok()) {
120 return linked.error();
121 }
122 return g_nativeloader_extra_libs_namespace;
123}
124
125// If the given path matches a library in NATIVELOADER_DEFAULT_NAMESPACE_LIBS
126// then load it in the nativeloader-extra-libs namespace, otherwise return
127// nullptr without error. This is only enabled if the ro.debuggable is true.
128Result<void*> TryLoadNativeloaderExtraLib(const char* path) {
129 if (!Debuggable()) {
130 return nullptr;
131 }
132 const char* links = getenv("NATIVELOADER_DEFAULT_NAMESPACE_LIBS");
133 if (links == nullptr || *links == 0) {
134 return nullptr;
135 }
136 std::vector<std::string> lib_list = base::Split(links, ":");
137 if (std::find(lib_list.begin(), lib_list.end(), path) == lib_list.end()) {
138 return nullptr;
139 }
140
141 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
142 Result<NativeLoaderNamespace*> ns = GetNativeloaderExtraLibsNamespace();
143 if (!ns.ok()) {
144 return ns.error();
145 }
146 return ns.value()->Load(path);
147}
148
149Result<NativeLoaderNamespace*> CreateClassLoaderNamespaceLocked(JNIEnv* env,
150 int32_t target_sdk_version,
151 jobject class_loader,
152 bool is_shared,
153 jstring dex_path,
154 jstring library_path,
155 jstring permitted_path,
156 jstring uses_library_list)
157 REQUIRES(g_namespaces_mutex) {
158 Result<NativeLoaderNamespace*> ns = g_namespaces->Create(env,
159 target_sdk_version,
160 class_loader,
161 is_shared,
162 dex_path,
163 library_path,
164 permitted_path,
165 uses_library_list);
166 if (!ns.ok()) {
167 return ns;
168 }
169 if (Debuggable()) {
170 Result<void> linked = CreateNativeloaderDefaultNamespaceLibsLink(*ns.value());
171 if (!linked.ok()) {
172 return linked.error();
173 }
174 }
175 return ns;
176}
177
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100178#endif // #if defined(ART_TARGET_ANDROID)
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100179
Orion Hodson9b16e342019-10-09 13:29:16 +0100180} // namespace
181
182void InitializeNativeLoader() {
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100183#if defined(ART_TARGET_ANDROID)
Orion Hodson9b16e342019-10-09 13:29:16 +0100184 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
185 g_namespaces->Initialize();
186#endif
187}
188
189void ResetNativeLoader() {
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100190#if defined(ART_TARGET_ANDROID)
Orion Hodson9b16e342019-10-09 13:29:16 +0100191 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
192 g_namespaces->Reset();
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100193 delete(g_nativeloader_extra_libs_namespace);
194 g_nativeloader_extra_libs_namespace = nullptr;
Orion Hodson9b16e342019-10-09 13:29:16 +0100195#endif
196}
197
198jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
199 bool is_shared, jstring dex_path, jstring library_path,
Jiyong Park14626a72020-07-02 23:17:58 +0900200 jstring permitted_path, jstring uses_library_list) {
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100201#if defined(ART_TARGET_ANDROID)
Orion Hodson9b16e342019-10-09 13:29:16 +0100202 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100203 Result<NativeLoaderNamespace*> ns = CreateClassLoaderNamespaceLocked(env,
204 target_sdk_version,
205 class_loader,
206 is_shared,
207 dex_path,
208 library_path,
209 permitted_path,
210 uses_library_list);
Bernie Innocenti4bd58952020-02-06 15:43:57 +0900211 if (!ns.ok()) {
Orion Hodson9b16e342019-10-09 13:29:16 +0100212 return env->NewStringUTF(ns.error().message().c_str());
213 }
214#else
Jiyong Park14626a72020-07-02 23:17:58 +0900215 UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path,
216 uses_library_list);
Orion Hodson9b16e342019-10-09 13:29:16 +0100217#endif
218 return nullptr;
219}
220
221void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
222 jobject class_loader, const char* caller_location, jstring library_path,
223 bool* needs_native_bridge, char** error_msg) {
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100224#if defined(ART_TARGET_ANDROID)
Orion Hodson9b16e342019-10-09 13:29:16 +0100225 UNUSED(target_sdk_version);
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100226
Orion Hodson9b16e342019-10-09 13:29:16 +0100227 if (class_loader == nullptr) {
228 *needs_native_bridge = false;
229 if (caller_location != nullptr) {
230 android_namespace_t* boot_namespace = FindExportedNamespace(caller_location);
231 if (boot_namespace != nullptr) {
232 const android_dlextinfo dlextinfo = {
233 .flags = ANDROID_DLEXT_USE_NAMESPACE,
234 .library_namespace = boot_namespace,
235 };
236 void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo);
237 if (handle == nullptr) {
238 *error_msg = strdup(dlerror());
239 }
240 return handle;
241 }
242 }
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100243
244 // Check if the library is in NATIVELOADER_DEFAULT_NAMESPACE_LIBS and should
245 // be loaded from the kNativeloaderExtraLibs namespace.
246 {
247 Result<void*> handle = TryLoadNativeloaderExtraLib(path);
248 if (!handle.ok()) {
249 *error_msg = strdup(handle.error().message().c_str());
250 return nullptr;
251 }
252 if (handle.value() != nullptr) {
253 return handle.value();
254 }
255 }
256
Orion Hodson9b16e342019-10-09 13:29:16 +0100257 void* handle = dlopen(path, RTLD_NOW);
258 if (handle == nullptr) {
259 *error_msg = strdup(dlerror());
260 }
261 return handle;
262 }
263
264 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
265 NativeLoaderNamespace* ns;
266
267 if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
268 // This is the case where the classloader was not created by ApplicationLoaders
269 // In this case we create an isolated not-shared namespace for it.
270 Result<NativeLoaderNamespace*> isolated_ns =
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100271 CreateClassLoaderNamespaceLocked(env,
272 target_sdk_version,
273 class_loader,
274 /*is_shared=*/false,
275 /*dex_path=*/nullptr,
276 library_path,
277 /*permitted_path=*/nullptr,
278 /*uses_library_list=*/nullptr);
Bernie Innocenti4bd58952020-02-06 15:43:57 +0900279 if (!isolated_ns.ok()) {
Orion Hodson9b16e342019-10-09 13:29:16 +0100280 *error_msg = strdup(isolated_ns.error().message().c_str());
281 return nullptr;
282 } else {
283 ns = *isolated_ns;
284 }
285 }
286
287 return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
288#else
289 UNUSED(env, target_sdk_version, class_loader, caller_location);
290
291 // Do some best effort to emulate library-path support. It will not
292 // work for dependencies.
293 //
294 // Note: null has a special meaning and must be preserved.
295 std::string c_library_path; // Empty string by default.
296 if (library_path != nullptr && path != nullptr && path[0] != '/') {
297 ScopedUtfChars library_path_utf_chars(env, library_path);
298 c_library_path = library_path_utf_chars.c_str();
299 }
300
301 std::vector<std::string> library_paths = base::Split(c_library_path, ":");
302
303 for (const std::string& lib_path : library_paths) {
304 *needs_native_bridge = false;
305 const char* path_arg;
306 std::string complete_path;
307 if (path == nullptr) {
308 // Preserve null.
309 path_arg = nullptr;
310 } else {
311 complete_path = lib_path;
312 if (!complete_path.empty()) {
313 complete_path.append("/");
314 }
315 complete_path.append(path);
316 path_arg = complete_path.c_str();
317 }
318 void* handle = dlopen(path_arg, RTLD_NOW);
319 if (handle != nullptr) {
320 return handle;
321 }
322 if (NativeBridgeIsSupported(path_arg)) {
323 *needs_native_bridge = true;
324 handle = NativeBridgeLoadLibrary(path_arg, RTLD_NOW);
325 if (handle != nullptr) {
326 return handle;
327 }
328 *error_msg = strdup(NativeBridgeGetError());
329 } else {
330 *error_msg = strdup(dlerror());
331 }
332 }
333 return nullptr;
334#endif
335}
336
337bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
338 bool success;
339 if (needs_native_bridge) {
340 success = (NativeBridgeUnloadLibrary(handle) == 0);
341 if (!success) {
342 *error_msg = strdup(NativeBridgeGetError());
343 }
344 } else {
345 success = (dlclose(handle) == 0);
346 if (!success) {
347 *error_msg = strdup(dlerror());
348 }
349 }
350
351 return success;
352}
353
354void NativeLoaderFreeErrorMessage(char* msg) {
355 // The error messages get allocated through strdup, so we must call free on them.
356 free(msg);
357}
358
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100359#if defined(ART_TARGET_ANDROID)
Orion Hodson9b16e342019-10-09 13:29:16 +0100360void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
361 bool* needs_native_bridge, char** error_msg) {
362 auto handle = ns->Load(path);
Bernie Innocenti4bd58952020-02-06 15:43:57 +0900363 if (!handle.ok() && error_msg != nullptr) {
Orion Hodson9b16e342019-10-09 13:29:16 +0100364 *error_msg = strdup(handle.error().message().c_str());
365 }
366 if (needs_native_bridge != nullptr) {
367 *needs_native_bridge = ns->IsBridged();
368 }
Bernie Innocenti4bd58952020-02-06 15:43:57 +0900369 return handle.ok() ? *handle : nullptr;
Orion Hodson9b16e342019-10-09 13:29:16 +0100370}
371
372// native_bridge_namespaces are not supported for callers of this function.
373// This function will return nullptr in the case when application is running
374// on native bridge.
375android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
376 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
377 NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader);
378 if (ns != nullptr && !ns->IsBridged()) {
379 return ns->ToRawAndroidNamespace();
380 }
381 return nullptr;
382}
383
384NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
385 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
386 return g_namespaces->FindNamespaceByClassLoader(env, class_loader);
387}
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100388
389void LinkNativeLoaderNamespaceToExportedNamespaceLibrary(struct NativeLoaderNamespace* ns,
390 const char* exported_ns_name,
391 const char* library_name,
392 char** error_msg) {
393 Result<NativeLoaderNamespace> exported_ns =
394 NativeLoaderNamespace::GetExportedNamespace(exported_ns_name, ns->IsBridged());
395 if (!exported_ns.ok()) {
396 *error_msg = strdup(exported_ns.error().message().c_str());
397 return;
398 }
399
400 Result<void> linked = ns->Link(&exported_ns.value(), std::string(library_name));
401 if (!linked.ok()) {
402 *error_msg = strdup(linked.error().message().c_str());
403 }
404}
405
406#endif // ART_TARGET_ANDROID
Orion Hodson9b16e342019-10-09 13:29:16 +0100407
408}; // namespace android