blob: 2deb5ef3d06d5e84c3ebe9399f7097c0d893fb05 [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>
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010033#include <android-base/thread_annotations.h>
Orion Hodson9b16e342019-10-09 13:29:16 +010034#include <nativebridge/native_bridge.h>
Orion Hodson6dc0a432020-02-06 14:28:28 +000035#include <nativehelper/scoped_utf_chars.h>
Orion Hodson9b16e342019-10-09 13:29:16 +010036
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +010037#ifdef ART_TARGET_ANDROID
Orion Hodson9b16e342019-10-09 13:29:16 +010038#include <log/log.h>
39#include "library_namespaces.h"
40#include "nativeloader/dlext_namespaces.h"
41#endif
42
43namespace android {
44
45namespace {
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010046
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +010047#if defined(ART_TARGET_ANDROID)
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010048
49// NATIVELOADER_DEFAULT_NAMESPACE_LIBS is an environment variable that can be
Martin Stjernholm7e363b82021-05-05 13:10:42 +010050// used to list extra libraries (separated by ":") that libnativeloader will
51// load from the default namespace. The libraries must be listed without paths,
52// and then LD_LIBRARY_PATH is typically set to the directories to load them
53// from. The libraries will be available in all classloader namespaces, and also
54// in the fallback namespace used when no classloader is given.
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010055//
56// kNativeloaderExtraLibs is the name of that fallback namespace.
57//
58// NATIVELOADER_DEFAULT_NAMESPACE_LIBS is intended to be used for testing only,
59// and in particular in the ART run tests that are executed through dalvikvm in
60// the APEX. In that case the default namespace links to the ART namespace
61// (com_android_art) for all libraries, which means this can be used to load
62// test libraries that depend on ART internal libraries.
63constexpr const char* kNativeloaderExtraLibs = "nativeloader-extra-libs";
64
Orion Hodson9b16e342019-10-09 13:29:16 +010065using android::nativeloader::LibraryNamespaces;
66
Orion Hodson9b16e342019-10-09 13:29:16 +010067std::mutex g_namespaces_mutex;
68LibraryNamespaces* g_namespaces = new LibraryNamespaces;
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010069NativeLoaderNamespace* g_nativeloader_extra_libs_namespace = nullptr;
Orion Hodson9b16e342019-10-09 13:29:16 +010070
71android_namespace_t* FindExportedNamespace(const char* caller_location) {
Jooyung Han538f99a2020-03-03 00:46:50 +090072 auto name = nativeloader::FindApexNamespaceName(caller_location);
73 if (name.ok()) {
74 android_namespace_t* boot_namespace = android_get_exported_namespace(name->c_str());
Orion Hodson9b16e342019-10-09 13:29:16 +010075 LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr),
Jooyung Han538f99a2020-03-03 00:46:50 +090076 "Error finding namespace of apex: no namespace called %s", name->c_str());
Orion Hodson9b16e342019-10-09 13:29:16 +010077 return boot_namespace;
78 }
79 return nullptr;
80}
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +010081
82Result<void> CreateNativeloaderDefaultNamespaceLibsLink(NativeLoaderNamespace& ns)
83 REQUIRES(g_namespaces_mutex) {
84 const char* links = getenv("NATIVELOADER_DEFAULT_NAMESPACE_LIBS");
85 if (links == nullptr || *links == 0) {
86 return {};
87 }
88 // Pass nullptr to Link() to create a link to the default namespace without
89 // requiring it to be visible.
90 return ns.Link(nullptr, links);
91}
92
93Result<NativeLoaderNamespace*> GetNativeloaderExtraLibsNamespace() REQUIRES(g_namespaces_mutex) {
94 if (g_nativeloader_extra_libs_namespace != nullptr) {
95 return g_nativeloader_extra_libs_namespace;
96 }
97
98 Result<NativeLoaderNamespace> ns =
99 NativeLoaderNamespace::Create(kNativeloaderExtraLibs,
100 /*search_paths=*/"",
101 /*permitted_paths=*/"",
102 /*parent=*/nullptr,
103 /*is_shared=*/false,
104 /*is_exempt_list_enabled=*/false,
105 /*also_used_as_anonymous=*/false);
106 if (!ns.ok()) {
107 return ns.error();
108 }
109 g_nativeloader_extra_libs_namespace = new NativeLoaderNamespace(std::move(ns.value()));
110 Result<void> linked =
111 CreateNativeloaderDefaultNamespaceLibsLink(*g_nativeloader_extra_libs_namespace);
112 if (!linked.ok()) {
113 return linked.error();
114 }
115 return g_nativeloader_extra_libs_namespace;
116}
117
118// If the given path matches a library in NATIVELOADER_DEFAULT_NAMESPACE_LIBS
119// then load it in the nativeloader-extra-libs namespace, otherwise return
Martin Stjernholm7e363b82021-05-05 13:10:42 +0100120// nullptr without error.
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100121Result<void*> TryLoadNativeloaderExtraLib(const char* path) {
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100122 const char* links = getenv("NATIVELOADER_DEFAULT_NAMESPACE_LIBS");
123 if (links == nullptr || *links == 0) {
124 return nullptr;
125 }
126 std::vector<std::string> lib_list = base::Split(links, ":");
127 if (std::find(lib_list.begin(), lib_list.end(), path) == lib_list.end()) {
128 return nullptr;
129 }
130
131 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
132 Result<NativeLoaderNamespace*> ns = GetNativeloaderExtraLibsNamespace();
133 if (!ns.ok()) {
134 return ns.error();
135 }
136 return ns.value()->Load(path);
137}
138
139Result<NativeLoaderNamespace*> CreateClassLoaderNamespaceLocked(JNIEnv* env,
140 int32_t target_sdk_version,
141 jobject class_loader,
142 bool is_shared,
143 jstring dex_path,
144 jstring library_path,
145 jstring permitted_path,
146 jstring uses_library_list)
147 REQUIRES(g_namespaces_mutex) {
148 Result<NativeLoaderNamespace*> ns = g_namespaces->Create(env,
149 target_sdk_version,
150 class_loader,
151 is_shared,
152 dex_path,
153 library_path,
154 permitted_path,
155 uses_library_list);
156 if (!ns.ok()) {
157 return ns;
158 }
Martin Stjernholm7e363b82021-05-05 13:10:42 +0100159 Result<void> linked = CreateNativeloaderDefaultNamespaceLibsLink(*ns.value());
160 if (!linked.ok()) {
161 return linked.error();
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100162 }
163 return ns;
164}
165
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100166#endif // #if defined(ART_TARGET_ANDROID)
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100167
Orion Hodson9b16e342019-10-09 13:29:16 +0100168} // namespace
169
170void InitializeNativeLoader() {
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100171#if defined(ART_TARGET_ANDROID)
Orion Hodson9b16e342019-10-09 13:29:16 +0100172 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
173 g_namespaces->Initialize();
174#endif
175}
176
177void ResetNativeLoader() {
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100178#if defined(ART_TARGET_ANDROID)
Orion Hodson9b16e342019-10-09 13:29:16 +0100179 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
180 g_namespaces->Reset();
Martin Stjernholm7e363b82021-05-05 13:10:42 +0100181 delete g_nativeloader_extra_libs_namespace;
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100182 g_nativeloader_extra_libs_namespace = nullptr;
Orion Hodson9b16e342019-10-09 13:29:16 +0100183#endif
184}
185
186jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
187 bool is_shared, jstring dex_path, jstring library_path,
Jiyong Park14626a72020-07-02 23:17:58 +0900188 jstring permitted_path, jstring uses_library_list) {
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100189#if defined(ART_TARGET_ANDROID)
Orion Hodson9b16e342019-10-09 13:29:16 +0100190 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100191 Result<NativeLoaderNamespace*> ns = CreateClassLoaderNamespaceLocked(env,
192 target_sdk_version,
193 class_loader,
194 is_shared,
195 dex_path,
196 library_path,
197 permitted_path,
198 uses_library_list);
Bernie Innocenti4bd58952020-02-06 15:43:57 +0900199 if (!ns.ok()) {
Orion Hodson9b16e342019-10-09 13:29:16 +0100200 return env->NewStringUTF(ns.error().message().c_str());
201 }
202#else
Jiyong Park14626a72020-07-02 23:17:58 +0900203 UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path,
204 uses_library_list);
Orion Hodson9b16e342019-10-09 13:29:16 +0100205#endif
206 return nullptr;
207}
208
209void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
210 jobject class_loader, const char* caller_location, jstring library_path,
211 bool* needs_native_bridge, char** error_msg) {
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100212#if defined(ART_TARGET_ANDROID)
Orion Hodson9b16e342019-10-09 13:29:16 +0100213 UNUSED(target_sdk_version);
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100214
Orion Hodson9b16e342019-10-09 13:29:16 +0100215 if (class_loader == nullptr) {
216 *needs_native_bridge = false;
217 if (caller_location != nullptr) {
218 android_namespace_t* boot_namespace = FindExportedNamespace(caller_location);
219 if (boot_namespace != nullptr) {
220 const android_dlextinfo dlextinfo = {
221 .flags = ANDROID_DLEXT_USE_NAMESPACE,
222 .library_namespace = boot_namespace,
223 };
224 void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo);
225 if (handle == nullptr) {
226 *error_msg = strdup(dlerror());
227 }
228 return handle;
229 }
230 }
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100231
232 // Check if the library is in NATIVELOADER_DEFAULT_NAMESPACE_LIBS and should
233 // be loaded from the kNativeloaderExtraLibs namespace.
234 {
235 Result<void*> handle = TryLoadNativeloaderExtraLib(path);
236 if (!handle.ok()) {
237 *error_msg = strdup(handle.error().message().c_str());
238 return nullptr;
239 }
240 if (handle.value() != nullptr) {
241 return handle.value();
242 }
243 }
244
Martin Stjernholm26659432021-04-16 19:55:03 +0100245 // Fall back to the system namespace. This happens for preloaded JNI
246 // libraries in the zygote.
247 // TODO(b/185833744): Investigate if this should fall back to the app main
248 // namespace (aka anonymous namespace) instead.
249 void* handle = OpenSystemLibrary(path, RTLD_NOW);
Orion Hodson9b16e342019-10-09 13:29:16 +0100250 if (handle == nullptr) {
251 *error_msg = strdup(dlerror());
252 }
253 return handle;
254 }
255
256 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
257 NativeLoaderNamespace* ns;
258
259 if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
260 // This is the case where the classloader was not created by ApplicationLoaders
261 // In this case we create an isolated not-shared namespace for it.
262 Result<NativeLoaderNamespace*> isolated_ns =
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100263 CreateClassLoaderNamespaceLocked(env,
264 target_sdk_version,
265 class_loader,
266 /*is_shared=*/false,
267 /*dex_path=*/nullptr,
268 library_path,
269 /*permitted_path=*/nullptr,
270 /*uses_library_list=*/nullptr);
Bernie Innocenti4bd58952020-02-06 15:43:57 +0900271 if (!isolated_ns.ok()) {
Orion Hodson9b16e342019-10-09 13:29:16 +0100272 *error_msg = strdup(isolated_ns.error().message().c_str());
273 return nullptr;
274 } else {
275 ns = *isolated_ns;
276 }
277 }
278
279 return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
280#else
281 UNUSED(env, target_sdk_version, class_loader, caller_location);
282
283 // Do some best effort to emulate library-path support. It will not
284 // work for dependencies.
285 //
286 // Note: null has a special meaning and must be preserved.
287 std::string c_library_path; // Empty string by default.
288 if (library_path != nullptr && path != nullptr && path[0] != '/') {
289 ScopedUtfChars library_path_utf_chars(env, library_path);
290 c_library_path = library_path_utf_chars.c_str();
291 }
292
293 std::vector<std::string> library_paths = base::Split(c_library_path, ":");
294
295 for (const std::string& lib_path : library_paths) {
296 *needs_native_bridge = false;
297 const char* path_arg;
298 std::string complete_path;
299 if (path == nullptr) {
300 // Preserve null.
301 path_arg = nullptr;
302 } else {
303 complete_path = lib_path;
304 if (!complete_path.empty()) {
305 complete_path.append("/");
306 }
307 complete_path.append(path);
308 path_arg = complete_path.c_str();
309 }
310 void* handle = dlopen(path_arg, RTLD_NOW);
311 if (handle != nullptr) {
312 return handle;
313 }
314 if (NativeBridgeIsSupported(path_arg)) {
315 *needs_native_bridge = true;
316 handle = NativeBridgeLoadLibrary(path_arg, RTLD_NOW);
317 if (handle != nullptr) {
318 return handle;
319 }
320 *error_msg = strdup(NativeBridgeGetError());
321 } else {
322 *error_msg = strdup(dlerror());
323 }
324 }
325 return nullptr;
326#endif
327}
328
329bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
330 bool success;
331 if (needs_native_bridge) {
332 success = (NativeBridgeUnloadLibrary(handle) == 0);
333 if (!success) {
334 *error_msg = strdup(NativeBridgeGetError());
335 }
336 } else {
337 success = (dlclose(handle) == 0);
338 if (!success) {
339 *error_msg = strdup(dlerror());
340 }
341 }
342
343 return success;
344}
345
346void NativeLoaderFreeErrorMessage(char* msg) {
347 // The error messages get allocated through strdup, so we must call free on them.
348 free(msg);
349}
350
Nicolas Geoffray7ca8b672020-04-24 15:43:48 +0100351#if defined(ART_TARGET_ANDROID)
Orion Hodson9b16e342019-10-09 13:29:16 +0100352void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
353 bool* needs_native_bridge, char** error_msg) {
354 auto handle = ns->Load(path);
Bernie Innocenti4bd58952020-02-06 15:43:57 +0900355 if (!handle.ok() && error_msg != nullptr) {
Orion Hodson9b16e342019-10-09 13:29:16 +0100356 *error_msg = strdup(handle.error().message().c_str());
357 }
358 if (needs_native_bridge != nullptr) {
359 *needs_native_bridge = ns->IsBridged();
360 }
Bernie Innocenti4bd58952020-02-06 15:43:57 +0900361 return handle.ok() ? *handle : nullptr;
Orion Hodson9b16e342019-10-09 13:29:16 +0100362}
363
364// native_bridge_namespaces are not supported for callers of this function.
365// This function will return nullptr in the case when application is running
366// on native bridge.
367android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
368 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
369 NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader);
370 if (ns != nullptr && !ns->IsBridged()) {
371 return ns->ToRawAndroidNamespace();
372 }
373 return nullptr;
374}
375
376NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
377 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
378 return g_namespaces->FindNamespaceByClassLoader(env, class_loader);
379}
Martin Stjernholm0d0f8df2021-04-28 16:47:01 +0100380
381void LinkNativeLoaderNamespaceToExportedNamespaceLibrary(struct NativeLoaderNamespace* ns,
382 const char* exported_ns_name,
383 const char* library_name,
384 char** error_msg) {
385 Result<NativeLoaderNamespace> exported_ns =
386 NativeLoaderNamespace::GetExportedNamespace(exported_ns_name, ns->IsBridged());
387 if (!exported_ns.ok()) {
388 *error_msg = strdup(exported_ns.error().message().c_str());
389 return;
390 }
391
392 Result<void> linked = ns->Link(&exported_ns.value(), std::string(library_name));
393 if (!linked.ok()) {
394 *error_msg = strdup(linked.error().message().c_str());
395 }
396}
397
398#endif // ART_TARGET_ANDROID
Orion Hodson9b16e342019-10-09 13:29:16 +0100399
400}; // namespace android