blob: 60d462f870a192649746eb64f7732229f8f7b469 [file] [log] [blame]
Dimitry Ivanovac1b1912015-12-01 13:56:44 -08001/*
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
Jiyong Park6291da22019-04-26 18:55:48 +090017#define LOG_TAG "nativeloader"
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080018
Jiyong Park16a98962019-05-04 03:10:48 +090019#include "nativeloader/native_loader.h"
20
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080021#include <dlfcn.h>
Jiyong Parkd1006fe2017-11-08 18:44:09 +090022#include <sys/types.h>
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080023
Jiyong Parkd1006fe2017-11-08 18:44:09 +090024#include <memory>
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080025#include <mutex>
Jiyong Parkd1006fe2017-11-08 18:44:09 +090026#include <string>
27#include <vector>
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080028
Jiyong Park16a98962019-05-04 03:10:48 +090029#include <android-base/file.h>
30#include <android-base/macros.h>
31#include <android-base/strings.h>
32#include <nativebridge/native_bridge.h>
33#include <nativehelper/ScopedUtfChars.h>
34
Jiyong Park6291da22019-04-26 18:55:48 +090035#ifdef __ANDROID__
Jiyong Park16a98962019-05-04 03:10:48 +090036#include <log/log.h>
Jiyong Park6291da22019-04-26 18:55:48 +090037#include "library_namespaces.h"
Jiyong Park6291da22019-04-26 18:55:48 +090038#include "nativeloader/dlext_namespaces.h"
Justin Yun4a1d1102017-11-27 17:04:14 +090039#endif
Inseob Kim67cb0562018-05-04 11:39:12 +090040
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080041namespace android {
42
Jiyong Park6291da22019-04-26 18:55:48 +090043namespace {
Dimitry Ivanov4b0e9632016-03-15 13:51:26 -070044#if defined(__ANDROID__)
Jiyong Park40a60772019-05-03 16:21:31 +090045using android::nativeloader::LibraryNamespaces;
46
Jiyong Park6291da22019-04-26 18:55:48 +090047constexpr const char* kApexPath = "/apex/";
Zhenhua WANGf2804e52016-05-30 11:16:08 +080048
Jiyong Park6291da22019-04-26 18:55:48 +090049std::mutex g_namespaces_mutex;
50LibraryNamespaces* g_namespaces = new LibraryNamespaces;
Zhenhua WANGf2804e52016-05-30 11:16:08 +080051
Jiyong Park6291da22019-04-26 18:55:48 +090052android_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:
55 // /apex/com.android...modulename/...
56 //
57 // And we extract from it 'modulename', which is the name of the linker namespace.
58 if (android::base::StartsWith(location, kApexPath)) {
59 size_t slash_index = location.find_first_of('/', strlen(kApexPath));
60 LOG_ALWAYS_FATAL_IF((slash_index == std::string::npos),
61 "Error finding namespace of apex: no slash in path %s", caller_location);
62 size_t dot_index = location.find_last_of('.', slash_index);
63 LOG_ALWAYS_FATAL_IF((dot_index == std::string::npos),
64 "Error finding namespace of apex: no dot in apex name %s", caller_location);
65 std::string name = location.substr(dot_index + 1, slash_index - dot_index - 1);
Martin Stjernholmdf96e1f2019-07-17 22:17:58 +010066 // TODO(b/139408016): Rename the runtime namespace to "art".
67 if (name == "art") {
68 name = "runtime";
69 }
Jiyong Park6291da22019-04-26 18:55:48 +090070 android_namespace_t* boot_namespace = android_get_exported_namespace(name.c_str());
71 LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr),
72 "Error finding namespace of apex: no namespace called %s", name.c_str());
73 return boot_namespace;
Zhenhua WANGf2804e52016-05-30 11:16:08 +080074 }
Jiyong Park6291da22019-04-26 18:55:48 +090075 return nullptr;
Dimitry Ivanov7d028292016-05-05 17:30:24 -070076}
Jiyong Park6291da22019-04-26 18:55:48 +090077#endif // #if defined(__ANDROID__)
78} // namespace
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080079
Dimitry Ivanov4b0e9632016-03-15 13:51:26 -070080void InitializeNativeLoader() {
Dimitry Ivanov426799d2016-02-22 11:27:48 -080081#if defined(__ANDROID__)
Dimitry Ivanov34d5a202016-02-29 13:21:43 -080082 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
Dimitry Ivanov4b0e9632016-03-15 13:51:26 -070083 g_namespaces->Initialize();
Dimitry Ivanov426799d2016-02-22 11:27:48 -080084#endif
85}
86
Dimitry Ivanovbe4ca3a2016-05-02 10:43:16 -070087void ResetNativeLoader() {
88#if defined(__ANDROID__)
89 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
90 g_namespaces->Reset();
91#endif
92}
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080093
Kiyoung Kim4639f692019-02-20 18:04:39 +090094jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
95 bool is_shared, jstring dex_path, jstring library_path,
Dimitry Ivanovd047c922016-02-23 14:23:51 -080096 jstring permitted_path) {
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080097#if defined(__ANDROID__)
Dimitry Ivanov34d5a202016-02-29 13:21:43 -080098 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
Jiyong Park8f4afc82019-07-22 14:20:40 +090099 auto ns = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
100 library_path, permitted_path);
101 if (!ns) {
102 return env->NewStringUTF(ns.error().message().c_str());
Dimitry Ivanovd047c922016-02-23 14:23:51 -0800103 }
104#else
Kiyoung Kim4639f692019-02-20 18:04:39 +0900105 UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path);
Dimitry Ivanovd047c922016-02-23 14:23:51 -0800106#endif
107 return nullptr;
108}
109
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000110void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
Nicolas Geoffray53535022019-01-18 10:05:13 +0000111 jobject class_loader, const char* caller_location, jstring library_path,
112 bool* needs_native_bridge, char** error_msg) {
Dimitry Ivanovd047c922016-02-23 14:23:51 -0800113#if defined(__ANDROID__)
Dimitry Ivanov5539db02016-04-20 16:07:30 -0700114 UNUSED(target_sdk_version);
115 if (class_loader == nullptr) {
Zhenhua WANGf2804e52016-05-30 11:16:08 +0800116 *needs_native_bridge = false;
Nicolas Geoffray890e3bf2019-01-22 09:11:57 +0000117 if (caller_location != nullptr) {
118 android_namespace_t* boot_namespace = FindExportedNamespace(caller_location);
119 if (boot_namespace != nullptr) {
120 const android_dlextinfo dlextinfo = {
121 .flags = ANDROID_DLEXT_USE_NAMESPACE,
122 .library_namespace = boot_namespace,
123 };
124 void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo);
125 if (handle == nullptr) {
126 *error_msg = strdup(dlerror());
127 }
128 return handle;
129 }
130 }
Pete Bentley632f1422018-12-19 13:33:33 +0000131 void* handle = dlopen(path, RTLD_NOW);
132 if (handle == nullptr) {
Nicolas Geoffrayd06cb942019-01-16 20:20:27 +0000133 *error_msg = strdup(dlerror());
Pete Bentley632f1422018-12-19 13:33:33 +0000134 }
135 return handle;
Dimitry Ivanovac1b1912015-12-01 13:56:44 -0800136 }
137
Dimitry Ivanov34d5a202016-02-29 13:21:43 -0800138 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
Victor Khimenko1443ec42018-07-09 17:01:22 +0200139 NativeLoaderNamespace* ns;
Dimitry Ivanovac1b1912015-12-01 13:56:44 -0800140
Victor Khimenko1443ec42018-07-09 17:01:22 +0200141 if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
Dimitry Ivanovd047c922016-02-23 14:23:51 -0800142 // This is the case where the classloader was not created by ApplicationLoaders
143 // In this case we create an isolated not-shared namespace for it.
Jiyong Park8f4afc82019-07-22 14:20:40 +0900144 Result<NativeLoaderNamespace*> isolated_ns =
145 g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */, nullptr,
146 library_path, nullptr);
147 if (!isolated_ns) {
148 *error_msg = strdup(isolated_ns.error().message().c_str());
Dimitry Ivanovd047c922016-02-23 14:23:51 -0800149 return nullptr;
Jiyong Park8f4afc82019-07-22 14:20:40 +0900150 } else {
151 ns = *isolated_ns;
Dimitry Ivanovd047c922016-02-23 14:23:51 -0800152 }
Dimitry Ivanovac1b1912015-12-01 13:56:44 -0800153 }
154
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000155 return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
Dimitry Ivanovac1b1912015-12-01 13:56:44 -0800156#else
Nicolas Geoffray53535022019-01-18 10:05:13 +0000157 UNUSED(env, target_sdk_version, class_loader, caller_location);
Andreas Gampe5c7d5822017-12-28 19:08:13 -0800158
159 // Do some best effort to emulate library-path support. It will not
160 // work for dependencies.
161 //
162 // Note: null has a special meaning and must be preserved.
163 std::string c_library_path; // Empty string by default.
164 if (library_path != nullptr && path != nullptr && path[0] != '/') {
165 ScopedUtfChars library_path_utf_chars(env, library_path);
166 c_library_path = library_path_utf_chars.c_str();
167 }
168
169 std::vector<std::string> library_paths = base::Split(c_library_path, ":");
170
171 for (const std::string& lib_path : library_paths) {
172 *needs_native_bridge = false;
173 const char* path_arg;
174 std::string complete_path;
175 if (path == nullptr) {
176 // Preserve null.
177 path_arg = nullptr;
Zhenhua WANGf2804e52016-05-30 11:16:08 +0800178 } else {
Andreas Gampe5c7d5822017-12-28 19:08:13 -0800179 complete_path = lib_path;
180 if (!complete_path.empty()) {
181 complete_path.append("/");
182 }
183 complete_path.append(path);
184 path_arg = complete_path.c_str();
185 }
186 void* handle = dlopen(path_arg, RTLD_NOW);
187 if (handle != nullptr) {
188 return handle;
189 }
190 if (NativeBridgeIsSupported(path_arg)) {
191 *needs_native_bridge = true;
192 handle = NativeBridgeLoadLibrary(path_arg, RTLD_NOW);
193 if (handle != nullptr) {
194 return handle;
195 }
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000196 *error_msg = strdup(NativeBridgeGetError());
Andreas Gampe5c7d5822017-12-28 19:08:13 -0800197 } else {
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000198 *error_msg = strdup(dlerror());
Zhenhua WANGf2804e52016-05-30 11:16:08 +0800199 }
200 }
Andreas Gampe5c7d5822017-12-28 19:08:13 -0800201 return nullptr;
Dimitry Ivanovac1b1912015-12-01 13:56:44 -0800202#endif
203}
204
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000205bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
dimitry3150f7c2018-09-12 01:09:19 +0200206 bool success;
207 if (needs_native_bridge) {
208 success = (NativeBridgeUnloadLibrary(handle) == 0);
209 if (!success) {
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000210 *error_msg = strdup(NativeBridgeGetError());
dimitry3150f7c2018-09-12 01:09:19 +0200211 }
212 } else {
213 success = (dlclose(handle) == 0);
214 if (!success) {
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000215 *error_msg = strdup(dlerror());
dimitry3150f7c2018-09-12 01:09:19 +0200216 }
217 }
218
219 return success;
Dimitry Ivanov09a516b2016-05-03 14:55:25 -0700220}
221
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000222void NativeLoaderFreeErrorMessage(char* msg) {
223 // The error messages get allocated through strdup, so we must call free on them.
224 free(msg);
225}
226
Dimitry Ivanovf44ecde2016-02-22 13:48:22 -0800227#if defined(__ANDROID__)
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000228void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
229 bool* needs_native_bridge, char** error_msg) {
Jiyong Park8f4afc82019-07-22 14:20:40 +0900230 auto handle = ns->Load(path);
231 if (!handle && error_msg != nullptr) {
232 *error_msg = strdup(handle.error().message().c_str());
Victor Khimenko1443ec42018-07-09 17:01:22 +0200233 }
Jiyong Park8f4afc82019-07-22 14:20:40 +0900234 if (needs_native_bridge != nullptr) {
235 *needs_native_bridge = ns->IsBridged();
236 }
237 return handle ? *handle : nullptr;
Victor Khimenko1443ec42018-07-09 17:01:22 +0200238}
239
Dimitry Ivanov800083d2016-11-01 14:17:00 -0700240// native_bridge_namespaces are not supported for callers of this function.
241// This function will return nullptr in the case when application is running
242// on native bridge.
Dimitry Ivanovf44ecde2016-02-22 13:48:22 -0800243android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
Dimitry Ivanov34d5a202016-02-29 13:21:43 -0800244 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
Victor Khimenko1443ec42018-07-09 17:01:22 +0200245 NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader);
Jiyong Park85377812019-05-04 00:30:23 +0900246 if (ns != nullptr && !ns->IsBridged()) {
247 return ns->ToRawAndroidNamespace();
Zhenhua WANGf2804e52016-05-30 11:16:08 +0800248 }
Zhenhua WANGf2804e52016-05-30 11:16:08 +0800249 return nullptr;
Dimitry Ivanovf44ecde2016-02-22 13:48:22 -0800250}
Jiyong Park6291da22019-04-26 18:55:48 +0900251
Victor Khimenko1443ec42018-07-09 17:01:22 +0200252NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
253 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
254 return g_namespaces->FindNamespaceByClassLoader(env, class_loader);
255}
Dimitry Ivanovf44ecde2016-02-22 13:48:22 -0800256#endif
257
Jiyong Park6291da22019-04-26 18:55:48 +0900258}; // namespace android