blob: ed98714ff665f4813baf1ff9d524f08f312afd5d [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
17#include "nativeloader/native_loader.h"
Jiyong Park6291da22019-04-26 18:55:48 +090018#define LOG_TAG "nativeloader"
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080019
20#include <dlfcn.h>
Jiyong Parkd1006fe2017-11-08 18:44:09 +090021#include <sys/types.h>
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080022
Jiyong Parkd1006fe2017-11-08 18:44:09 +090023#include <memory>
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080024#include <mutex>
Jiyong Parkd1006fe2017-11-08 18:44:09 +090025#include <string>
26#include <vector>
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080027
Jiyong Park6291da22019-04-26 18:55:48 +090028#include "android-base/file.h"
29#include "android-base/macros.h"
30#include "android-base/strings.h"
31#ifdef __ANDROID__
32#include "library_namespaces.h"
33#include "log/log.h"
34#include "nativeloader/dlext_namespaces.h"
Justin Yun4a1d1102017-11-27 17:04:14 +090035#endif
Jiyong Park6291da22019-04-26 18:55:48 +090036#include "nativebridge/native_bridge.h"
37#include "nativehelper/ScopedUtfChars.h"
Inseob Kim67cb0562018-05-04 11:39:12 +090038
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080039namespace android {
40
Jiyong Park6291da22019-04-26 18:55:48 +090041namespace {
Dimitry Ivanov4b0e9632016-03-15 13:51:26 -070042#if defined(__ANDROID__)
Jiyong Park6291da22019-04-26 18:55:48 +090043constexpr const char* kApexPath = "/apex/";
Zhenhua WANGf2804e52016-05-30 11:16:08 +080044
Jiyong Park6291da22019-04-26 18:55:48 +090045std::mutex g_namespaces_mutex;
46LibraryNamespaces* g_namespaces = new LibraryNamespaces;
Zhenhua WANGf2804e52016-05-30 11:16:08 +080047
Jiyong Park6291da22019-04-26 18:55:48 +090048android_namespace_t* FindExportedNamespace(const char* caller_location) {
49 std::string location = caller_location;
50 // Lots of implicit assumptions here: we expect `caller_location` to be of the form:
51 // /apex/com.android...modulename/...
52 //
53 // And we extract from it 'modulename', which is the name of the linker namespace.
54 if (android::base::StartsWith(location, kApexPath)) {
55 size_t slash_index = location.find_first_of('/', strlen(kApexPath));
56 LOG_ALWAYS_FATAL_IF((slash_index == std::string::npos),
57 "Error finding namespace of apex: no slash in path %s", caller_location);
58 size_t dot_index = location.find_last_of('.', slash_index);
59 LOG_ALWAYS_FATAL_IF((dot_index == std::string::npos),
60 "Error finding namespace of apex: no dot in apex name %s", caller_location);
61 std::string name = location.substr(dot_index + 1, slash_index - dot_index - 1);
62 android_namespace_t* boot_namespace = android_get_exported_namespace(name.c_str());
63 LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr),
64 "Error finding namespace of apex: no namespace called %s", name.c_str());
65 return boot_namespace;
Zhenhua WANGf2804e52016-05-30 11:16:08 +080066 }
Jiyong Park6291da22019-04-26 18:55:48 +090067 return nullptr;
Dimitry Ivanov7d028292016-05-05 17:30:24 -070068}
Jiyong Park6291da22019-04-26 18:55:48 +090069#endif // #if defined(__ANDROID__)
70} // namespace
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080071
Dimitry Ivanov4b0e9632016-03-15 13:51:26 -070072void InitializeNativeLoader() {
Dimitry Ivanov426799d2016-02-22 11:27:48 -080073#if defined(__ANDROID__)
Dimitry Ivanov34d5a202016-02-29 13:21:43 -080074 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
Dimitry Ivanov4b0e9632016-03-15 13:51:26 -070075 g_namespaces->Initialize();
Dimitry Ivanov426799d2016-02-22 11:27:48 -080076#endif
77}
78
Dimitry Ivanovbe4ca3a2016-05-02 10:43:16 -070079void ResetNativeLoader() {
80#if defined(__ANDROID__)
81 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
82 g_namespaces->Reset();
83#endif
84}
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080085
Kiyoung Kim4639f692019-02-20 18:04:39 +090086jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
87 bool is_shared, jstring dex_path, jstring library_path,
Dimitry Ivanovd047c922016-02-23 14:23:51 -080088 jstring permitted_path) {
Dimitry Ivanovac1b1912015-12-01 13:56:44 -080089#if defined(__ANDROID__)
Dimitry Ivanov34d5a202016-02-29 13:21:43 -080090 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
Zhenhua WANGf2804e52016-05-30 11:16:08 +080091
92 std::string error_msg;
Kiyoung Kim4639f692019-02-20 18:04:39 +090093 bool success = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
94 library_path, permitted_path, &error_msg) != nullptr;
Zhenhua WANGf2804e52016-05-30 11:16:08 +080095 if (!success) {
96 return env->NewStringUTF(error_msg.c_str());
Dimitry Ivanovd047c922016-02-23 14:23:51 -080097 }
98#else
Kiyoung Kim4639f692019-02-20 18:04:39 +090099 UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path);
Dimitry Ivanovd047c922016-02-23 14:23:51 -0800100#endif
101 return nullptr;
102}
103
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000104void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
Nicolas Geoffray53535022019-01-18 10:05:13 +0000105 jobject class_loader, const char* caller_location, jstring library_path,
106 bool* needs_native_bridge, char** error_msg) {
Dimitry Ivanovd047c922016-02-23 14:23:51 -0800107#if defined(__ANDROID__)
Dimitry Ivanov5539db02016-04-20 16:07:30 -0700108 UNUSED(target_sdk_version);
109 if (class_loader == nullptr) {
Zhenhua WANGf2804e52016-05-30 11:16:08 +0800110 *needs_native_bridge = false;
Nicolas Geoffray890e3bf2019-01-22 09:11:57 +0000111 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 }
Pete Bentley632f1422018-12-19 13:33:33 +0000125 void* handle = dlopen(path, RTLD_NOW);
126 if (handle == nullptr) {
Nicolas Geoffrayd06cb942019-01-16 20:20:27 +0000127 *error_msg = strdup(dlerror());
Pete Bentley632f1422018-12-19 13:33:33 +0000128 }
129 return handle;
Dimitry Ivanovac1b1912015-12-01 13:56:44 -0800130 }
131
Dimitry Ivanov34d5a202016-02-29 13:21:43 -0800132 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
Victor Khimenko1443ec42018-07-09 17:01:22 +0200133 NativeLoaderNamespace* ns;
Dimitry Ivanovac1b1912015-12-01 13:56:44 -0800134
Victor Khimenko1443ec42018-07-09 17:01:22 +0200135 if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
Dimitry Ivanovd047c922016-02-23 14:23:51 -0800136 // 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.
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000138 std::string create_error_msg;
139 if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */,
Kiyoung Kim4639f692019-02-20 18:04:39 +0900140 nullptr, library_path, nullptr, &create_error_msg)) == nullptr) {
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000141 *error_msg = strdup(create_error_msg.c_str());
Dimitry Ivanovd047c922016-02-23 14:23:51 -0800142 return nullptr;
143 }
Dimitry Ivanovac1b1912015-12-01 13:56:44 -0800144 }
145
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000146 return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
Dimitry Ivanovac1b1912015-12-01 13:56:44 -0800147#else
Nicolas Geoffray53535022019-01-18 10:05:13 +0000148 UNUSED(env, target_sdk_version, class_loader, caller_location);
Andreas Gampe5c7d5822017-12-28 19:08:13 -0800149
150 // Do some best effort to emulate library-path support. It will not
151 // work for dependencies.
152 //
153 // Note: null has a special meaning and must be preserved.
154 std::string c_library_path; // Empty string by default.
155 if (library_path != nullptr && path != nullptr && path[0] != '/') {
156 ScopedUtfChars library_path_utf_chars(env, library_path);
157 c_library_path = library_path_utf_chars.c_str();
158 }
159
160 std::vector<std::string> library_paths = base::Split(c_library_path, ":");
161
162 for (const std::string& lib_path : library_paths) {
163 *needs_native_bridge = false;
164 const char* path_arg;
165 std::string complete_path;
166 if (path == nullptr) {
167 // Preserve null.
168 path_arg = nullptr;
Zhenhua WANGf2804e52016-05-30 11:16:08 +0800169 } else {
Andreas Gampe5c7d5822017-12-28 19:08:13 -0800170 complete_path = lib_path;
171 if (!complete_path.empty()) {
172 complete_path.append("/");
173 }
174 complete_path.append(path);
175 path_arg = complete_path.c_str();
176 }
177 void* handle = dlopen(path_arg, RTLD_NOW);
178 if (handle != nullptr) {
179 return handle;
180 }
181 if (NativeBridgeIsSupported(path_arg)) {
182 *needs_native_bridge = true;
183 handle = NativeBridgeLoadLibrary(path_arg, RTLD_NOW);
184 if (handle != nullptr) {
185 return handle;
186 }
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000187 *error_msg = strdup(NativeBridgeGetError());
Andreas Gampe5c7d5822017-12-28 19:08:13 -0800188 } else {
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000189 *error_msg = strdup(dlerror());
Zhenhua WANGf2804e52016-05-30 11:16:08 +0800190 }
191 }
Andreas Gampe5c7d5822017-12-28 19:08:13 -0800192 return nullptr;
Dimitry Ivanovac1b1912015-12-01 13:56:44 -0800193#endif
194}
195
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000196bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
dimitry3150f7c2018-09-12 01:09:19 +0200197 bool success;
198 if (needs_native_bridge) {
199 success = (NativeBridgeUnloadLibrary(handle) == 0);
200 if (!success) {
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000201 *error_msg = strdup(NativeBridgeGetError());
dimitry3150f7c2018-09-12 01:09:19 +0200202 }
203 } else {
204 success = (dlclose(handle) == 0);
205 if (!success) {
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000206 *error_msg = strdup(dlerror());
dimitry3150f7c2018-09-12 01:09:19 +0200207 }
208 }
209
210 return success;
Dimitry Ivanov09a516b2016-05-03 14:55:25 -0700211}
212
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000213void NativeLoaderFreeErrorMessage(char* msg) {
214 // The error messages get allocated through strdup, so we must call free on them.
215 free(msg);
216}
217
Dimitry Ivanovf44ecde2016-02-22 13:48:22 -0800218#if defined(__ANDROID__)
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000219void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
220 bool* needs_native_bridge, char** error_msg) {
Victor Khimenko1443ec42018-07-09 17:01:22 +0200221 if (ns->is_android_namespace()) {
222 android_dlextinfo extinfo;
223 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
224 extinfo.library_namespace = ns->get_android_ns();
225
226 void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo);
227 if (handle == nullptr) {
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000228 *error_msg = strdup(dlerror());
Victor Khimenko1443ec42018-07-09 17:01:22 +0200229 }
230 *needs_native_bridge = false;
231 return handle;
232 } else {
233 void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns->get_native_bridge_ns());
234 if (handle == nullptr) {
Nicolas Geoffrayc3a73dc2019-01-12 15:01:20 +0000235 *error_msg = strdup(NativeBridgeGetError());
Victor Khimenko1443ec42018-07-09 17:01:22 +0200236 }
237 *needs_native_bridge = true;
238 return handle;
239 }
240}
241
Dimitry Ivanov800083d2016-11-01 14:17:00 -0700242// native_bridge_namespaces are not supported for callers of this function.
243// This function will return nullptr in the case when application is running
244// on native bridge.
Dimitry Ivanovf44ecde2016-02-22 13:48:22 -0800245android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
Dimitry Ivanov34d5a202016-02-29 13:21:43 -0800246 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
Victor Khimenko1443ec42018-07-09 17:01:22 +0200247 NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader);
248 if (ns != nullptr) {
249 return ns->is_android_namespace() ? ns->get_android_ns() : nullptr;
Zhenhua WANGf2804e52016-05-30 11:16:08 +0800250 }
251
252 return nullptr;
Dimitry Ivanovf44ecde2016-02-22 13:48:22 -0800253}
Jiyong Park6291da22019-04-26 18:55:48 +0900254
Victor Khimenko1443ec42018-07-09 17:01:22 +0200255NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
256 std::lock_guard<std::mutex> guard(g_namespaces_mutex);
257 return g_namespaces->FindNamespaceByClassLoader(env, class_loader);
258}
Dimitry Ivanovf44ecde2016-02-22 13:48:22 -0800259#endif
260
Jiyong Park6291da22019-04-26 18:55:48 +0900261}; // namespace android