xref: /aosp_15_r20/art/libnativeloader/native_loader.cpp (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #define LOG_TAG "nativeloader"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "nativeloader/native_loader.h"
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker #include <dlfcn.h>
22*795d594fSAndroid Build Coastguard Worker #include <sys/types.h>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include <algorithm>
25*795d594fSAndroid Build Coastguard Worker #include <memory>
26*795d594fSAndroid Build Coastguard Worker #include <mutex>
27*795d594fSAndroid Build Coastguard Worker #include <optional>
28*795d594fSAndroid Build Coastguard Worker #include <regex>
29*795d594fSAndroid Build Coastguard Worker #include <string>
30*795d594fSAndroid Build Coastguard Worker #include <vector>
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker #include "android-base/file.h"
33*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
34*795d594fSAndroid Build Coastguard Worker #include <android-base/properties.h>
35*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
36*795d594fSAndroid Build Coastguard Worker #include "android-base/thread_annotations.h"
37*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
38*795d594fSAndroid Build Coastguard Worker #include "nativebridge/native_bridge.h"
39*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_utf_chars.h"
40*795d594fSAndroid Build Coastguard Worker #include "public_libraries.h"
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker #ifdef ART_TARGET_ANDROID
43*795d594fSAndroid Build Coastguard Worker #include "android-modules-utils/sdk_level.h"
44*795d594fSAndroid Build Coastguard Worker #include "android/api-level.h"
45*795d594fSAndroid Build Coastguard Worker #include "library_namespaces.h"
46*795d594fSAndroid Build Coastguard Worker #include "log/log.h"
47*795d594fSAndroid Build Coastguard Worker #include "nativeloader/dlext_namespaces.h"
48*795d594fSAndroid Build Coastguard Worker #endif
49*795d594fSAndroid Build Coastguard Worker 
50*795d594fSAndroid Build Coastguard Worker namespace android {
51*795d594fSAndroid Build Coastguard Worker 
52*795d594fSAndroid Build Coastguard Worker namespace {
53*795d594fSAndroid Build Coastguard Worker 
54*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker using ::android::base::Result;
57*795d594fSAndroid Build Coastguard Worker using ::android::nativeloader::LibraryNamespaces;
58*795d594fSAndroid Build Coastguard Worker 
59*795d594fSAndroid Build Coastguard Worker // NATIVELOADER_DEFAULT_NAMESPACE_LIBS is an environment variable that can be
60*795d594fSAndroid Build Coastguard Worker // used to list extra libraries (separated by ":") that libnativeloader will
61*795d594fSAndroid Build Coastguard Worker // load from the default namespace. The libraries must be listed without paths,
62*795d594fSAndroid Build Coastguard Worker // and then LD_LIBRARY_PATH is typically set to the directories to load them
63*795d594fSAndroid Build Coastguard Worker // from. The libraries will be available in all classloader namespaces, and also
64*795d594fSAndroid Build Coastguard Worker // in the fallback namespace used when no classloader is given.
65*795d594fSAndroid Build Coastguard Worker //
66*795d594fSAndroid Build Coastguard Worker // kNativeloaderExtraLibs is the name of that fallback namespace.
67*795d594fSAndroid Build Coastguard Worker //
68*795d594fSAndroid Build Coastguard Worker // NATIVELOADER_DEFAULT_NAMESPACE_LIBS is intended to be used for testing only,
69*795d594fSAndroid Build Coastguard Worker // and in particular in the ART run tests that are executed through dalvikvm in
70*795d594fSAndroid Build Coastguard Worker // the APEX. In that case the default namespace links to the ART namespace
71*795d594fSAndroid Build Coastguard Worker // (com_android_art) for all libraries, which means this can be used to load
72*795d594fSAndroid Build Coastguard Worker // test libraries that depend on ART internal libraries.
73*795d594fSAndroid Build Coastguard Worker constexpr const char* kNativeloaderExtraLibs = "nativeloader-extra-libs";
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker std::mutex g_namespaces_mutex;
76*795d594fSAndroid Build Coastguard Worker LibraryNamespaces* g_namespaces GUARDED_BY(g_namespaces_mutex) = new LibraryNamespaces;
77*795d594fSAndroid Build Coastguard Worker NativeLoaderNamespace* g_nativeloader_extra_libs_namespace GUARDED_BY(g_namespaces_mutex) = nullptr;
78*795d594fSAndroid Build Coastguard Worker 
FindApexNamespace(const char * caller_location)79*795d594fSAndroid Build Coastguard Worker std::optional<NativeLoaderNamespace> FindApexNamespace(const char* caller_location) {
80*795d594fSAndroid Build Coastguard Worker   std::optional<std::string> name = nativeloader::FindApexNamespaceName(caller_location);
81*795d594fSAndroid Build Coastguard Worker   if (name.has_value()) {
82*795d594fSAndroid Build Coastguard Worker     // Native Bridge is never used for APEXes.
83*795d594fSAndroid Build Coastguard Worker     Result<NativeLoaderNamespace> ns =
84*795d594fSAndroid Build Coastguard Worker         NativeLoaderNamespace::GetExportedNamespace(name.value(), /*is_bridged=*/false);
85*795d594fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(!ns.ok(),
86*795d594fSAndroid Build Coastguard Worker                         "Error finding ns %s for APEX location %s: %s",
87*795d594fSAndroid Build Coastguard Worker                         name.value().c_str(),
88*795d594fSAndroid Build Coastguard Worker                         caller_location,
89*795d594fSAndroid Build Coastguard Worker                         ns.error().message().c_str());
90*795d594fSAndroid Build Coastguard Worker     return ns.value();
91*795d594fSAndroid Build Coastguard Worker   }
92*795d594fSAndroid Build Coastguard Worker   return std::nullopt;
93*795d594fSAndroid Build Coastguard Worker }
94*795d594fSAndroid Build Coastguard Worker 
GetNamespaceForApiDomain(nativeloader::ApiDomain api_domain,bool is_bridged)95*795d594fSAndroid Build Coastguard Worker Result<NativeLoaderNamespace> GetNamespaceForApiDomain(nativeloader::ApiDomain api_domain,
96*795d594fSAndroid Build Coastguard Worker                                                        bool is_bridged) {
97*795d594fSAndroid Build Coastguard Worker   switch (api_domain) {
98*795d594fSAndroid Build Coastguard Worker     case nativeloader::API_DOMAIN_VENDOR:
99*795d594fSAndroid Build Coastguard Worker       return NativeLoaderNamespace::GetExportedNamespace(nativeloader::kVendorNamespaceName,
100*795d594fSAndroid Build Coastguard Worker                                                          is_bridged);
101*795d594fSAndroid Build Coastguard Worker     case nativeloader::API_DOMAIN_PRODUCT:
102*795d594fSAndroid Build Coastguard Worker       return NativeLoaderNamespace::GetExportedNamespace(nativeloader::kProductNamespaceName,
103*795d594fSAndroid Build Coastguard Worker                                                          is_bridged);
104*795d594fSAndroid Build Coastguard Worker     case nativeloader::API_DOMAIN_SYSTEM:
105*795d594fSAndroid Build Coastguard Worker       return NativeLoaderNamespace::GetSystemNamespace(is_bridged);
106*795d594fSAndroid Build Coastguard Worker     default:
107*795d594fSAndroid Build Coastguard Worker       LOG_FATAL("Invalid API domain %d", api_domain);
108*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
109*795d594fSAndroid Build Coastguard Worker   }
110*795d594fSAndroid Build Coastguard Worker }
111*795d594fSAndroid Build Coastguard Worker 
CreateNativeloaderDefaultNamespaceLibsLink(NativeLoaderNamespace & ns)112*795d594fSAndroid Build Coastguard Worker Result<void> CreateNativeloaderDefaultNamespaceLibsLink(NativeLoaderNamespace& ns)
113*795d594fSAndroid Build Coastguard Worker     REQUIRES(g_namespaces_mutex) {
114*795d594fSAndroid Build Coastguard Worker   const char* links = getenv("NATIVELOADER_DEFAULT_NAMESPACE_LIBS");
115*795d594fSAndroid Build Coastguard Worker   if (links == nullptr || *links == 0) {
116*795d594fSAndroid Build Coastguard Worker     return {};
117*795d594fSAndroid Build Coastguard Worker   }
118*795d594fSAndroid Build Coastguard Worker   // Pass nullptr to Link() to create a link to the default namespace without
119*795d594fSAndroid Build Coastguard Worker   // requiring it to be visible.
120*795d594fSAndroid Build Coastguard Worker   return ns.Link(nullptr, links);
121*795d594fSAndroid Build Coastguard Worker }
122*795d594fSAndroid Build Coastguard Worker 
GetNativeloaderExtraLibsNamespace()123*795d594fSAndroid Build Coastguard Worker Result<NativeLoaderNamespace*> GetNativeloaderExtraLibsNamespace() REQUIRES(g_namespaces_mutex) {
124*795d594fSAndroid Build Coastguard Worker   if (g_nativeloader_extra_libs_namespace != nullptr) {
125*795d594fSAndroid Build Coastguard Worker     return g_nativeloader_extra_libs_namespace;
126*795d594fSAndroid Build Coastguard Worker   }
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker   Result<NativeLoaderNamespace> ns =
129*795d594fSAndroid Build Coastguard Worker       NativeLoaderNamespace::Create(kNativeloaderExtraLibs,
130*795d594fSAndroid Build Coastguard Worker                                     /*search_paths=*/"",
131*795d594fSAndroid Build Coastguard Worker                                     /*permitted_paths=*/"",
132*795d594fSAndroid Build Coastguard Worker                                     /*parent=*/nullptr,
133*795d594fSAndroid Build Coastguard Worker                                     /*is_shared=*/false,
134*795d594fSAndroid Build Coastguard Worker                                     /*is_exempt_list_enabled=*/false,
135*795d594fSAndroid Build Coastguard Worker                                     /*also_used_as_anonymous=*/false);
136*795d594fSAndroid Build Coastguard Worker   if (!ns.ok()) {
137*795d594fSAndroid Build Coastguard Worker     return ns.error();
138*795d594fSAndroid Build Coastguard Worker   }
139*795d594fSAndroid Build Coastguard Worker   g_nativeloader_extra_libs_namespace = new NativeLoaderNamespace(std::move(ns.value()));
140*795d594fSAndroid Build Coastguard Worker   Result<void> linked =
141*795d594fSAndroid Build Coastguard Worker       CreateNativeloaderDefaultNamespaceLibsLink(*g_nativeloader_extra_libs_namespace);
142*795d594fSAndroid Build Coastguard Worker   if (!linked.ok()) {
143*795d594fSAndroid Build Coastguard Worker     return linked.error();
144*795d594fSAndroid Build Coastguard Worker   }
145*795d594fSAndroid Build Coastguard Worker   return g_nativeloader_extra_libs_namespace;
146*795d594fSAndroid Build Coastguard Worker }
147*795d594fSAndroid Build Coastguard Worker 
148*795d594fSAndroid Build Coastguard Worker // If the given path matches a library in NATIVELOADER_DEFAULT_NAMESPACE_LIBS
149*795d594fSAndroid Build Coastguard Worker // then load it in the nativeloader-extra-libs namespace, otherwise return
150*795d594fSAndroid Build Coastguard Worker // nullptr without error.
TryLoadNativeloaderExtraLib(const char * path)151*795d594fSAndroid Build Coastguard Worker Result<void*> TryLoadNativeloaderExtraLib(const char* path) {
152*795d594fSAndroid Build Coastguard Worker   const char* links = getenv("NATIVELOADER_DEFAULT_NAMESPACE_LIBS");
153*795d594fSAndroid Build Coastguard Worker   if (links == nullptr || *links == 0) {
154*795d594fSAndroid Build Coastguard Worker     return nullptr;
155*795d594fSAndroid Build Coastguard Worker   }
156*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> lib_list = base::Split(links, ":");
157*795d594fSAndroid Build Coastguard Worker   if (std::find(lib_list.begin(), lib_list.end(), path) == lib_list.end()) {
158*795d594fSAndroid Build Coastguard Worker     return nullptr;
159*795d594fSAndroid Build Coastguard Worker   }
160*795d594fSAndroid Build Coastguard Worker 
161*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
162*795d594fSAndroid Build Coastguard Worker   Result<NativeLoaderNamespace*> ns = GetNativeloaderExtraLibsNamespace();
163*795d594fSAndroid Build Coastguard Worker   if (!ns.ok()) {
164*795d594fSAndroid Build Coastguard Worker     return ns.error();
165*795d594fSAndroid Build Coastguard Worker   }
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker   Result<void*> res = ns.value()->Load(path);
168*795d594fSAndroid Build Coastguard Worker   ALOGD("Load %s using ns %s from NATIVELOADER_DEFAULT_NAMESPACE_LIBS match: %s",
169*795d594fSAndroid Build Coastguard Worker         path,
170*795d594fSAndroid Build Coastguard Worker         ns.value()->name().c_str(),
171*795d594fSAndroid Build Coastguard Worker         res.ok() ? "ok" : res.error().message().c_str());
172*795d594fSAndroid Build Coastguard Worker   return res;
173*795d594fSAndroid Build Coastguard Worker }
174*795d594fSAndroid Build Coastguard Worker 
CreateClassLoaderNamespaceLocked(JNIEnv * env,int32_t target_sdk_version,jobject class_loader,nativeloader::ApiDomain api_domain,bool is_shared,const std::string & dex_path,jstring library_path_j,jstring permitted_path_j,jstring uses_library_list_j)175*795d594fSAndroid Build Coastguard Worker Result<NativeLoaderNamespace*> CreateClassLoaderNamespaceLocked(JNIEnv* env,
176*795d594fSAndroid Build Coastguard Worker                                                                 int32_t target_sdk_version,
177*795d594fSAndroid Build Coastguard Worker                                                                 jobject class_loader,
178*795d594fSAndroid Build Coastguard Worker                                                                 nativeloader::ApiDomain api_domain,
179*795d594fSAndroid Build Coastguard Worker                                                                 bool is_shared,
180*795d594fSAndroid Build Coastguard Worker                                                                 const std::string& dex_path,
181*795d594fSAndroid Build Coastguard Worker                                                                 jstring library_path_j,
182*795d594fSAndroid Build Coastguard Worker                                                                 jstring permitted_path_j,
183*795d594fSAndroid Build Coastguard Worker                                                                 jstring uses_library_list_j)
184*795d594fSAndroid Build Coastguard Worker     REQUIRES(g_namespaces_mutex) {
185*795d594fSAndroid Build Coastguard Worker   Result<NativeLoaderNamespace*> ns = g_namespaces->Create(env,
186*795d594fSAndroid Build Coastguard Worker                                                            target_sdk_version,
187*795d594fSAndroid Build Coastguard Worker                                                            class_loader,
188*795d594fSAndroid Build Coastguard Worker                                                            api_domain,
189*795d594fSAndroid Build Coastguard Worker                                                            is_shared,
190*795d594fSAndroid Build Coastguard Worker                                                            dex_path,
191*795d594fSAndroid Build Coastguard Worker                                                            library_path_j,
192*795d594fSAndroid Build Coastguard Worker                                                            permitted_path_j,
193*795d594fSAndroid Build Coastguard Worker                                                            uses_library_list_j);
194*795d594fSAndroid Build Coastguard Worker   if (!ns.ok()) {
195*795d594fSAndroid Build Coastguard Worker     return ns;
196*795d594fSAndroid Build Coastguard Worker   }
197*795d594fSAndroid Build Coastguard Worker   Result<void> linked = CreateNativeloaderDefaultNamespaceLibsLink(*ns.value());
198*795d594fSAndroid Build Coastguard Worker   if (!linked.ok()) {
199*795d594fSAndroid Build Coastguard Worker     return linked.error();
200*795d594fSAndroid Build Coastguard Worker   }
201*795d594fSAndroid Build Coastguard Worker   return ns;
202*795d594fSAndroid Build Coastguard Worker }
203*795d594fSAndroid Build Coastguard Worker 
204*795d594fSAndroid Build Coastguard Worker #endif  // ART_TARGET_ANDROID
205*795d594fSAndroid Build Coastguard Worker 
206*795d594fSAndroid Build Coastguard Worker }  // namespace
207*795d594fSAndroid Build Coastguard Worker 
InitializeNativeLoader()208*795d594fSAndroid Build Coastguard Worker void InitializeNativeLoader() {
209*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
210*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
211*795d594fSAndroid Build Coastguard Worker   g_namespaces->Initialize();
212*795d594fSAndroid Build Coastguard Worker #endif
213*795d594fSAndroid Build Coastguard Worker }
214*795d594fSAndroid Build Coastguard Worker 
ResetNativeLoader()215*795d594fSAndroid Build Coastguard Worker void ResetNativeLoader() {
216*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
217*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
218*795d594fSAndroid Build Coastguard Worker   g_namespaces->Reset();
219*795d594fSAndroid Build Coastguard Worker   delete g_nativeloader_extra_libs_namespace;
220*795d594fSAndroid Build Coastguard Worker   g_nativeloader_extra_libs_namespace = nullptr;
221*795d594fSAndroid Build Coastguard Worker #endif
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker 
224*795d594fSAndroid Build Coastguard Worker // dex_path_j may be a ':'-separated list of paths, e.g. when creating a shared
225*795d594fSAndroid Build Coastguard Worker // library loader - cf. mCodePaths in android.content.pm.SharedLibraryInfo.
CreateClassLoaderNamespace(JNIEnv * env,int32_t target_sdk_version,jobject class_loader,bool is_shared,jstring dex_path_j,jstring library_path_j,jstring permitted_path_j,jstring uses_library_list_j)226*795d594fSAndroid Build Coastguard Worker jstring CreateClassLoaderNamespace(JNIEnv* env,
227*795d594fSAndroid Build Coastguard Worker                                    int32_t target_sdk_version,
228*795d594fSAndroid Build Coastguard Worker                                    jobject class_loader,
229*795d594fSAndroid Build Coastguard Worker                                    bool is_shared,
230*795d594fSAndroid Build Coastguard Worker                                    jstring dex_path_j,
231*795d594fSAndroid Build Coastguard Worker                                    jstring library_path_j,
232*795d594fSAndroid Build Coastguard Worker                                    jstring permitted_path_j,
233*795d594fSAndroid Build Coastguard Worker                                    jstring uses_library_list_j) {
234*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
235*795d594fSAndroid Build Coastguard Worker   std::string dex_path;
236*795d594fSAndroid Build Coastguard Worker   if (dex_path_j != nullptr) {
237*795d594fSAndroid Build Coastguard Worker     ScopedUtfChars dex_path_chars(env, dex_path_j);
238*795d594fSAndroid Build Coastguard Worker     dex_path = dex_path_chars.c_str();
239*795d594fSAndroid Build Coastguard Worker   }
240*795d594fSAndroid Build Coastguard Worker 
241*795d594fSAndroid Build Coastguard Worker   Result<nativeloader::ApiDomain> api_domain = nativeloader::GetApiDomainFromPathList(dex_path);
242*795d594fSAndroid Build Coastguard Worker   if (!api_domain.ok()) {
243*795d594fSAndroid Build Coastguard Worker     return env->NewStringUTF(api_domain.error().message().c_str());
244*795d594fSAndroid Build Coastguard Worker   }
245*795d594fSAndroid Build Coastguard Worker 
246*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
247*795d594fSAndroid Build Coastguard Worker   Result<NativeLoaderNamespace*> ns = CreateClassLoaderNamespaceLocked(env,
248*795d594fSAndroid Build Coastguard Worker                                                                        target_sdk_version,
249*795d594fSAndroid Build Coastguard Worker                                                                        class_loader,
250*795d594fSAndroid Build Coastguard Worker                                                                        api_domain.value(),
251*795d594fSAndroid Build Coastguard Worker                                                                        is_shared,
252*795d594fSAndroid Build Coastguard Worker                                                                        dex_path,
253*795d594fSAndroid Build Coastguard Worker                                                                        library_path_j,
254*795d594fSAndroid Build Coastguard Worker                                                                        permitted_path_j,
255*795d594fSAndroid Build Coastguard Worker                                                                        uses_library_list_j);
256*795d594fSAndroid Build Coastguard Worker   if (!ns.ok()) {
257*795d594fSAndroid Build Coastguard Worker     return env->NewStringUTF(ns.error().message().c_str());
258*795d594fSAndroid Build Coastguard Worker   }
259*795d594fSAndroid Build Coastguard Worker 
260*795d594fSAndroid Build Coastguard Worker #else
261*795d594fSAndroid Build Coastguard Worker   UNUSED(env,
262*795d594fSAndroid Build Coastguard Worker          target_sdk_version,
263*795d594fSAndroid Build Coastguard Worker          class_loader,
264*795d594fSAndroid Build Coastguard Worker          is_shared,
265*795d594fSAndroid Build Coastguard Worker          dex_path_j,
266*795d594fSAndroid Build Coastguard Worker          library_path_j,
267*795d594fSAndroid Build Coastguard Worker          permitted_path_j,
268*795d594fSAndroid Build Coastguard Worker          uses_library_list_j);
269*795d594fSAndroid Build Coastguard Worker #endif
270*795d594fSAndroid Build Coastguard Worker 
271*795d594fSAndroid Build Coastguard Worker   return nullptr;
272*795d594fSAndroid Build Coastguard Worker }
273*795d594fSAndroid Build Coastguard Worker 
274*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
ShouldBypassLoadingForB349878424()275*795d594fSAndroid Build Coastguard Worker static bool ShouldBypassLoadingForB349878424() {
276*795d594fSAndroid Build Coastguard Worker   struct stat st;
277*795d594fSAndroid Build Coastguard Worker   if (stat("/system/lib64/libsobridge.so", &st) != 0 &&
278*795d594fSAndroid Build Coastguard Worker       stat("/system/lib64/libwalkstack.so", &st) != 0) {
279*795d594fSAndroid Build Coastguard Worker     return false;
280*795d594fSAndroid Build Coastguard Worker   }
281*795d594fSAndroid Build Coastguard Worker   std::string property = android::base::GetProperty("ro.product.build.fingerprint", "");
282*795d594fSAndroid Build Coastguard Worker   return android_get_device_api_level() == 33 &&
283*795d594fSAndroid Build Coastguard Worker       (property.starts_with("Xiaomi") ||
284*795d594fSAndroid Build Coastguard Worker        property.starts_with("Redmi") ||
285*795d594fSAndroid Build Coastguard Worker        property.starts_with("POCO"));
286*795d594fSAndroid Build Coastguard Worker }
287*795d594fSAndroid Build Coastguard Worker #endif
288*795d594fSAndroid Build Coastguard Worker 
OpenNativeLibrary(JNIEnv * env,int32_t target_sdk_version,const char * path,jobject class_loader,const char * caller_location,jstring library_path_j,bool * needs_native_bridge,char ** error_msg)289*795d594fSAndroid Build Coastguard Worker void* OpenNativeLibrary(JNIEnv* env,
290*795d594fSAndroid Build Coastguard Worker                         int32_t target_sdk_version,
291*795d594fSAndroid Build Coastguard Worker                         const char* path,
292*795d594fSAndroid Build Coastguard Worker                         jobject class_loader,
293*795d594fSAndroid Build Coastguard Worker                         const char* caller_location,
294*795d594fSAndroid Build Coastguard Worker                         jstring library_path_j,
295*795d594fSAndroid Build Coastguard Worker                         bool* needs_native_bridge,
296*795d594fSAndroid Build Coastguard Worker                         char** error_msg) {
297*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
298*795d594fSAndroid Build Coastguard Worker   if (class_loader == nullptr) {
299*795d594fSAndroid Build Coastguard Worker     // class_loader is null only for the boot class loader (see
300*795d594fSAndroid Build Coastguard Worker     // IsBootClassLoader call in JavaVMExt::LoadNativeLibrary), i.e. the caller
301*795d594fSAndroid Build Coastguard Worker     // is in the boot classpath.
302*795d594fSAndroid Build Coastguard Worker     *needs_native_bridge = false;
303*795d594fSAndroid Build Coastguard Worker     if (caller_location != nullptr) {
304*795d594fSAndroid Build Coastguard Worker       std::optional<NativeLoaderNamespace> ns = FindApexNamespace(caller_location);
305*795d594fSAndroid Build Coastguard Worker       if (ns.has_value()) {
306*795d594fSAndroid Build Coastguard Worker         const android_dlextinfo dlextinfo = {
307*795d594fSAndroid Build Coastguard Worker             .flags = ANDROID_DLEXT_USE_NAMESPACE,
308*795d594fSAndroid Build Coastguard Worker             .library_namespace = ns.value().ToRawAndroidNamespace(),
309*795d594fSAndroid Build Coastguard Worker         };
310*795d594fSAndroid Build Coastguard Worker         void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo);
311*795d594fSAndroid Build Coastguard Worker         char* dlerror_msg = handle == nullptr ? strdup(dlerror()) : nullptr;
312*795d594fSAndroid Build Coastguard Worker         ALOGD("Load %s using APEX ns %s for caller %s: %s",
313*795d594fSAndroid Build Coastguard Worker               path,
314*795d594fSAndroid Build Coastguard Worker               ns.value().name().c_str(),
315*795d594fSAndroid Build Coastguard Worker               caller_location,
316*795d594fSAndroid Build Coastguard Worker               dlerror_msg == nullptr ? "ok" : dlerror_msg);
317*795d594fSAndroid Build Coastguard Worker         if (dlerror_msg != nullptr) {
318*795d594fSAndroid Build Coastguard Worker           *error_msg = dlerror_msg;
319*795d594fSAndroid Build Coastguard Worker         }
320*795d594fSAndroid Build Coastguard Worker         return handle;
321*795d594fSAndroid Build Coastguard Worker       }
322*795d594fSAndroid Build Coastguard Worker     }
323*795d594fSAndroid Build Coastguard Worker 
324*795d594fSAndroid Build Coastguard Worker     // Check if the library is in NATIVELOADER_DEFAULT_NAMESPACE_LIBS and should
325*795d594fSAndroid Build Coastguard Worker     // be loaded from the kNativeloaderExtraLibs namespace.
326*795d594fSAndroid Build Coastguard Worker     {
327*795d594fSAndroid Build Coastguard Worker       Result<void*> handle = TryLoadNativeloaderExtraLib(path);
328*795d594fSAndroid Build Coastguard Worker       if (!handle.ok()) {
329*795d594fSAndroid Build Coastguard Worker         *error_msg = strdup(handle.error().message().c_str());
330*795d594fSAndroid Build Coastguard Worker         return nullptr;
331*795d594fSAndroid Build Coastguard Worker       }
332*795d594fSAndroid Build Coastguard Worker       if (handle.value() != nullptr) {
333*795d594fSAndroid Build Coastguard Worker         return handle.value();
334*795d594fSAndroid Build Coastguard Worker       }
335*795d594fSAndroid Build Coastguard Worker     }
336*795d594fSAndroid Build Coastguard Worker 
337*795d594fSAndroid Build Coastguard Worker     // Handle issue b/349878424.
338*795d594fSAndroid Build Coastguard Worker     static bool bypass_loading_for_b349878424 = ShouldBypassLoadingForB349878424();
339*795d594fSAndroid Build Coastguard Worker 
340*795d594fSAndroid Build Coastguard Worker     if (bypass_loading_for_b349878424 &&
341*795d594fSAndroid Build Coastguard Worker         (strcmp("libsobridge.so", path) == 0 || strcmp("libwalkstack.so", path) == 0)) {
342*795d594fSAndroid Build Coastguard Worker       // Load a different library to pretend the loading was successful. This
343*795d594fSAndroid Build Coastguard Worker       // allows the device to boot.
344*795d594fSAndroid Build Coastguard Worker       ALOGD("Loading libbase.so instead of %s due to b/349878424", path);
345*795d594fSAndroid Build Coastguard Worker       path = "libbase.so";
346*795d594fSAndroid Build Coastguard Worker     }
347*795d594fSAndroid Build Coastguard Worker 
348*795d594fSAndroid Build Coastguard Worker     // Fall back to the system namespace. This happens for preloaded JNI
349*795d594fSAndroid Build Coastguard Worker     // libraries in the zygote.
350*795d594fSAndroid Build Coastguard Worker     void* handle = OpenSystemLibrary(path, RTLD_NOW);
351*795d594fSAndroid Build Coastguard Worker     char* dlerror_msg = handle == nullptr ? strdup(dlerror()) : nullptr;
352*795d594fSAndroid Build Coastguard Worker     ALOGD("Load %s using system ns (caller=%s): %s",
353*795d594fSAndroid Build Coastguard Worker           path,
354*795d594fSAndroid Build Coastguard Worker           caller_location == nullptr ? "<unknown>" : caller_location,
355*795d594fSAndroid Build Coastguard Worker           dlerror_msg == nullptr ? "ok" : dlerror_msg);
356*795d594fSAndroid Build Coastguard Worker     if (dlerror_msg != nullptr) {
357*795d594fSAndroid Build Coastguard Worker       *error_msg = dlerror_msg;
358*795d594fSAndroid Build Coastguard Worker     }
359*795d594fSAndroid Build Coastguard Worker     return handle;
360*795d594fSAndroid Build Coastguard Worker   }
361*795d594fSAndroid Build Coastguard Worker 
362*795d594fSAndroid Build Coastguard Worker   // If the caller is in any of the system image partitions and the library is
363*795d594fSAndroid Build Coastguard Worker   // in the same partition then load it without regards to public library
364*795d594fSAndroid Build Coastguard Worker   // restrictions. This is only done if the library is specified by an absolute
365*795d594fSAndroid Build Coastguard Worker   // path, so we don't affect the lookup process for libraries specified by name
366*795d594fSAndroid Build Coastguard Worker   // only.
367*795d594fSAndroid Build Coastguard Worker   if (caller_location != nullptr &&
368*795d594fSAndroid Build Coastguard Worker       // Apps in the partition may have their own native libraries which should
369*795d594fSAndroid Build Coastguard Worker       // be loaded with the app's classloader namespace, so only do this for
370*795d594fSAndroid Build Coastguard Worker       // libraries in the partition-wide lib(64) directories.
371*795d594fSAndroid Build Coastguard Worker       nativeloader::IsPartitionNativeLibPath(path) &&
372*795d594fSAndroid Build Coastguard Worker       // Don't do this if the system image is older than V, to avoid any compat
373*795d594fSAndroid Build Coastguard Worker       // issues with apps and shared libs in them.
374*795d594fSAndroid Build Coastguard Worker       android::modules::sdklevel::IsAtLeastV()) {
375*795d594fSAndroid Build Coastguard Worker     nativeloader::ApiDomain caller_api_domain = nativeloader::GetApiDomainFromPath(caller_location);
376*795d594fSAndroid Build Coastguard Worker     if (caller_api_domain != nativeloader::API_DOMAIN_DEFAULT) {
377*795d594fSAndroid Build Coastguard Worker       nativeloader::ApiDomain library_api_domain = nativeloader::GetApiDomainFromPath(path);
378*795d594fSAndroid Build Coastguard Worker 
379*795d594fSAndroid Build Coastguard Worker       if (library_api_domain == caller_api_domain) {
380*795d594fSAndroid Build Coastguard Worker         bool is_bridged = false;
381*795d594fSAndroid Build Coastguard Worker         if (library_path_j != nullptr) {
382*795d594fSAndroid Build Coastguard Worker           ScopedUtfChars library_path_utf_chars(env, library_path_j);
383*795d594fSAndroid Build Coastguard Worker           if (library_path_utf_chars[0] != '\0') {
384*795d594fSAndroid Build Coastguard Worker             is_bridged = NativeBridgeIsPathSupported(library_path_utf_chars.c_str());
385*795d594fSAndroid Build Coastguard Worker           }
386*795d594fSAndroid Build Coastguard Worker         }
387*795d594fSAndroid Build Coastguard Worker 
388*795d594fSAndroid Build Coastguard Worker         Result<NativeLoaderNamespace> ns = GetNamespaceForApiDomain(caller_api_domain, is_bridged);
389*795d594fSAndroid Build Coastguard Worker         if (!ns.ok()) {
390*795d594fSAndroid Build Coastguard Worker           ALOGD("Failed to find ns for caller %s in API domain %d to load %s (is_bridged=%b): %s",
391*795d594fSAndroid Build Coastguard Worker                 caller_location,
392*795d594fSAndroid Build Coastguard Worker                 caller_api_domain,
393*795d594fSAndroid Build Coastguard Worker                 path,
394*795d594fSAndroid Build Coastguard Worker                 is_bridged,
395*795d594fSAndroid Build Coastguard Worker                 ns.error().message().c_str());
396*795d594fSAndroid Build Coastguard Worker           *error_msg = strdup(ns.error().message().c_str());
397*795d594fSAndroid Build Coastguard Worker           return nullptr;
398*795d594fSAndroid Build Coastguard Worker         }
399*795d594fSAndroid Build Coastguard Worker 
400*795d594fSAndroid Build Coastguard Worker         *needs_native_bridge = ns.value().IsBridged();
401*795d594fSAndroid Build Coastguard Worker         Result<void*> handle = ns.value().Load(path);
402*795d594fSAndroid Build Coastguard Worker         ALOGD("Load %s using ns %s for caller %s in same partition (is_bridged=%b): %s",
403*795d594fSAndroid Build Coastguard Worker               path,
404*795d594fSAndroid Build Coastguard Worker               ns.value().name().c_str(),
405*795d594fSAndroid Build Coastguard Worker               caller_location,
406*795d594fSAndroid Build Coastguard Worker               is_bridged,
407*795d594fSAndroid Build Coastguard Worker               handle.ok() ? "ok" : handle.error().message().c_str());
408*795d594fSAndroid Build Coastguard Worker         if (!handle.ok()) {
409*795d594fSAndroid Build Coastguard Worker           *error_msg = strdup(handle.error().message().c_str());
410*795d594fSAndroid Build Coastguard Worker           return nullptr;
411*795d594fSAndroid Build Coastguard Worker         }
412*795d594fSAndroid Build Coastguard Worker         return handle.value();
413*795d594fSAndroid Build Coastguard Worker       }
414*795d594fSAndroid Build Coastguard Worker     }
415*795d594fSAndroid Build Coastguard Worker   }
416*795d594fSAndroid Build Coastguard Worker 
417*795d594fSAndroid Build Coastguard Worker   NativeLoaderNamespace* ns;
418*795d594fSAndroid Build Coastguard Worker   const char* ns_descr;
419*795d594fSAndroid Build Coastguard Worker   {
420*795d594fSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> guard(g_namespaces_mutex);
421*795d594fSAndroid Build Coastguard Worker 
422*795d594fSAndroid Build Coastguard Worker     ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader);
423*795d594fSAndroid Build Coastguard Worker     ns_descr = "class loader";
424*795d594fSAndroid Build Coastguard Worker 
425*795d594fSAndroid Build Coastguard Worker     if (ns == nullptr) {
426*795d594fSAndroid Build Coastguard Worker       // This is the case where the classloader was not created by ApplicationLoaders
427*795d594fSAndroid Build Coastguard Worker       // In this case we create an isolated not-shared namespace for it.
428*795d594fSAndroid Build Coastguard Worker       const std::string empty_dex_path;
429*795d594fSAndroid Build Coastguard Worker       Result<NativeLoaderNamespace*> res =
430*795d594fSAndroid Build Coastguard Worker           CreateClassLoaderNamespaceLocked(env,
431*795d594fSAndroid Build Coastguard Worker                                            target_sdk_version,
432*795d594fSAndroid Build Coastguard Worker                                            class_loader,
433*795d594fSAndroid Build Coastguard Worker                                            nativeloader::API_DOMAIN_DEFAULT,
434*795d594fSAndroid Build Coastguard Worker                                            /*is_shared=*/false,
435*795d594fSAndroid Build Coastguard Worker                                            empty_dex_path,
436*795d594fSAndroid Build Coastguard Worker                                            library_path_j,
437*795d594fSAndroid Build Coastguard Worker                                            /*permitted_path_j=*/nullptr,
438*795d594fSAndroid Build Coastguard Worker                                            /*uses_library_list_j=*/nullptr);
439*795d594fSAndroid Build Coastguard Worker       if (!res.ok()) {
440*795d594fSAndroid Build Coastguard Worker         ALOGD("Failed to create isolated ns for %s (caller=%s)",
441*795d594fSAndroid Build Coastguard Worker               path,
442*795d594fSAndroid Build Coastguard Worker               caller_location == nullptr ? "<unknown>" : caller_location);
443*795d594fSAndroid Build Coastguard Worker         *error_msg = strdup(res.error().message().c_str());
444*795d594fSAndroid Build Coastguard Worker         return nullptr;
445*795d594fSAndroid Build Coastguard Worker       }
446*795d594fSAndroid Build Coastguard Worker       ns = res.value();
447*795d594fSAndroid Build Coastguard Worker       ns_descr = "isolated";
448*795d594fSAndroid Build Coastguard Worker     }
449*795d594fSAndroid Build Coastguard Worker   }
450*795d594fSAndroid Build Coastguard Worker 
451*795d594fSAndroid Build Coastguard Worker   *needs_native_bridge = ns->IsBridged();
452*795d594fSAndroid Build Coastguard Worker   Result<void*> handle = ns->Load(path);
453*795d594fSAndroid Build Coastguard Worker   ALOGD("Load %s using %s ns %s (caller=%s): %s",
454*795d594fSAndroid Build Coastguard Worker         path,
455*795d594fSAndroid Build Coastguard Worker         ns_descr,
456*795d594fSAndroid Build Coastguard Worker         ns->name().c_str(),
457*795d594fSAndroid Build Coastguard Worker         caller_location == nullptr ? "<unknown>" : caller_location,
458*795d594fSAndroid Build Coastguard Worker         handle.ok() ? "ok" : handle.error().message().c_str());
459*795d594fSAndroid Build Coastguard Worker   if (!handle.ok()) {
460*795d594fSAndroid Build Coastguard Worker     *error_msg = strdup(handle.error().message().c_str());
461*795d594fSAndroid Build Coastguard Worker     return nullptr;
462*795d594fSAndroid Build Coastguard Worker   }
463*795d594fSAndroid Build Coastguard Worker   return handle.value();
464*795d594fSAndroid Build Coastguard Worker 
465*795d594fSAndroid Build Coastguard Worker #else   // !ART_TARGET_ANDROID
466*795d594fSAndroid Build Coastguard Worker   UNUSED(env, target_sdk_version, class_loader, caller_location);
467*795d594fSAndroid Build Coastguard Worker 
468*795d594fSAndroid Build Coastguard Worker   // Do some best effort to emulate library-path support. It will not
469*795d594fSAndroid Build Coastguard Worker   // work for dependencies.
470*795d594fSAndroid Build Coastguard Worker   //
471*795d594fSAndroid Build Coastguard Worker   // Note: null has a special meaning and must be preserved.
472*795d594fSAndroid Build Coastguard Worker   std::string library_path;  // Empty string by default.
473*795d594fSAndroid Build Coastguard Worker   if (library_path_j != nullptr && path != nullptr && path[0] != '/') {
474*795d594fSAndroid Build Coastguard Worker     ScopedUtfChars library_path_utf_chars(env, library_path_j);
475*795d594fSAndroid Build Coastguard Worker     library_path = library_path_utf_chars.c_str();
476*795d594fSAndroid Build Coastguard Worker   }
477*795d594fSAndroid Build Coastguard Worker 
478*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> library_paths = base::Split(library_path, ":");
479*795d594fSAndroid Build Coastguard Worker 
480*795d594fSAndroid Build Coastguard Worker   for (const std::string& lib_path : library_paths) {
481*795d594fSAndroid Build Coastguard Worker     *needs_native_bridge = false;
482*795d594fSAndroid Build Coastguard Worker     const char* path_arg;
483*795d594fSAndroid Build Coastguard Worker     std::string complete_path;
484*795d594fSAndroid Build Coastguard Worker     if (path == nullptr) {
485*795d594fSAndroid Build Coastguard Worker       // Preserve null.
486*795d594fSAndroid Build Coastguard Worker       path_arg = nullptr;
487*795d594fSAndroid Build Coastguard Worker     } else {
488*795d594fSAndroid Build Coastguard Worker       complete_path = lib_path;
489*795d594fSAndroid Build Coastguard Worker       if (!complete_path.empty()) {
490*795d594fSAndroid Build Coastguard Worker         complete_path.append("/");
491*795d594fSAndroid Build Coastguard Worker       }
492*795d594fSAndroid Build Coastguard Worker       complete_path.append(path);
493*795d594fSAndroid Build Coastguard Worker       path_arg = complete_path.c_str();
494*795d594fSAndroid Build Coastguard Worker     }
495*795d594fSAndroid Build Coastguard Worker     void* handle = dlopen(path_arg, RTLD_NOW);
496*795d594fSAndroid Build Coastguard Worker     if (handle != nullptr) {
497*795d594fSAndroid Build Coastguard Worker       return handle;
498*795d594fSAndroid Build Coastguard Worker     }
499*795d594fSAndroid Build Coastguard Worker     if (NativeBridgeIsSupported(path_arg)) {
500*795d594fSAndroid Build Coastguard Worker       *needs_native_bridge = true;
501*795d594fSAndroid Build Coastguard Worker       handle = NativeBridgeLoadLibrary(path_arg, RTLD_NOW);
502*795d594fSAndroid Build Coastguard Worker       if (handle != nullptr) {
503*795d594fSAndroid Build Coastguard Worker         return handle;
504*795d594fSAndroid Build Coastguard Worker       }
505*795d594fSAndroid Build Coastguard Worker       *error_msg = strdup(NativeBridgeGetError());
506*795d594fSAndroid Build Coastguard Worker     } else {
507*795d594fSAndroid Build Coastguard Worker       *error_msg = strdup(dlerror());
508*795d594fSAndroid Build Coastguard Worker     }
509*795d594fSAndroid Build Coastguard Worker   }
510*795d594fSAndroid Build Coastguard Worker   return nullptr;
511*795d594fSAndroid Build Coastguard Worker #endif  // !ART_TARGET_ANDROID
512*795d594fSAndroid Build Coastguard Worker }
513*795d594fSAndroid Build Coastguard Worker 
CloseNativeLibrary(void * handle,const bool needs_native_bridge,char ** error_msg)514*795d594fSAndroid Build Coastguard Worker bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
515*795d594fSAndroid Build Coastguard Worker   bool success;
516*795d594fSAndroid Build Coastguard Worker   if (needs_native_bridge) {
517*795d594fSAndroid Build Coastguard Worker     success = (NativeBridgeUnloadLibrary(handle) == 0);
518*795d594fSAndroid Build Coastguard Worker     if (!success) {
519*795d594fSAndroid Build Coastguard Worker       *error_msg = strdup(NativeBridgeGetError());
520*795d594fSAndroid Build Coastguard Worker     }
521*795d594fSAndroid Build Coastguard Worker   } else {
522*795d594fSAndroid Build Coastguard Worker     success = (dlclose(handle) == 0);
523*795d594fSAndroid Build Coastguard Worker     if (!success) {
524*795d594fSAndroid Build Coastguard Worker       *error_msg = strdup(dlerror());
525*795d594fSAndroid Build Coastguard Worker     }
526*795d594fSAndroid Build Coastguard Worker   }
527*795d594fSAndroid Build Coastguard Worker 
528*795d594fSAndroid Build Coastguard Worker   return success;
529*795d594fSAndroid Build Coastguard Worker }
530*795d594fSAndroid Build Coastguard Worker 
NativeLoaderFreeErrorMessage(char * msg)531*795d594fSAndroid Build Coastguard Worker void NativeLoaderFreeErrorMessage(char* msg) {
532*795d594fSAndroid Build Coastguard Worker   // The error messages get allocated through strdup, so we must call free on them.
533*795d594fSAndroid Build Coastguard Worker   free(msg);
534*795d594fSAndroid Build Coastguard Worker }
535*795d594fSAndroid Build Coastguard Worker 
536*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
OpenNativeLibraryInNamespace(NativeLoaderNamespace * ns,const char * path,bool * needs_native_bridge,char ** error_msg)537*795d594fSAndroid Build Coastguard Worker void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
538*795d594fSAndroid Build Coastguard Worker                                    bool* needs_native_bridge, char** error_msg) {
539*795d594fSAndroid Build Coastguard Worker   Result<void*> handle = ns->Load(path);
540*795d594fSAndroid Build Coastguard Worker   if (!handle.ok() && error_msg != nullptr) {
541*795d594fSAndroid Build Coastguard Worker     *error_msg = strdup(handle.error().message().c_str());
542*795d594fSAndroid Build Coastguard Worker   }
543*795d594fSAndroid Build Coastguard Worker   if (needs_native_bridge != nullptr) {
544*795d594fSAndroid Build Coastguard Worker     *needs_native_bridge = ns->IsBridged();
545*795d594fSAndroid Build Coastguard Worker   }
546*795d594fSAndroid Build Coastguard Worker   return handle.ok() ? *handle : nullptr;
547*795d594fSAndroid Build Coastguard Worker }
548*795d594fSAndroid Build Coastguard Worker 
IsNamespaceNativeBridged(const struct NativeLoaderNamespace * ns)549*795d594fSAndroid Build Coastguard Worker bool IsNamespaceNativeBridged(const struct NativeLoaderNamespace* ns) { return ns->IsBridged(); }
550*795d594fSAndroid Build Coastguard Worker 
551*795d594fSAndroid Build Coastguard Worker // native_bridge_namespaces are not supported for callers of this function.
552*795d594fSAndroid Build Coastguard Worker // This function will return nullptr in the case when application is running
553*795d594fSAndroid Build Coastguard Worker // on native bridge.
FindNamespaceByClassLoader(JNIEnv * env,jobject class_loader)554*795d594fSAndroid Build Coastguard Worker android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
555*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
556*795d594fSAndroid Build Coastguard Worker   NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader);
557*795d594fSAndroid Build Coastguard Worker   if (ns != nullptr && !ns->IsBridged()) {
558*795d594fSAndroid Build Coastguard Worker     return ns->ToRawAndroidNamespace();
559*795d594fSAndroid Build Coastguard Worker   }
560*795d594fSAndroid Build Coastguard Worker   return nullptr;
561*795d594fSAndroid Build Coastguard Worker }
562*795d594fSAndroid Build Coastguard Worker 
FindNativeLoaderNamespaceByClassLoader(JNIEnv * env,jobject class_loader)563*795d594fSAndroid Build Coastguard Worker NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
564*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
565*795d594fSAndroid Build Coastguard Worker   return g_namespaces->FindNamespaceByClassLoader(env, class_loader);
566*795d594fSAndroid Build Coastguard Worker }
567*795d594fSAndroid Build Coastguard Worker 
LinkNativeLoaderNamespaceToExportedNamespaceLibrary(struct NativeLoaderNamespace * ns,const char * exported_ns_name,const char * library_name,char ** error_msg)568*795d594fSAndroid Build Coastguard Worker void LinkNativeLoaderNamespaceToExportedNamespaceLibrary(struct NativeLoaderNamespace* ns,
569*795d594fSAndroid Build Coastguard Worker                                                          const char* exported_ns_name,
570*795d594fSAndroid Build Coastguard Worker                                                          const char* library_name,
571*795d594fSAndroid Build Coastguard Worker                                                          char** error_msg) {
572*795d594fSAndroid Build Coastguard Worker   Result<NativeLoaderNamespace> exported_ns =
573*795d594fSAndroid Build Coastguard Worker       NativeLoaderNamespace::GetExportedNamespace(exported_ns_name, ns->IsBridged());
574*795d594fSAndroid Build Coastguard Worker   if (!exported_ns.ok()) {
575*795d594fSAndroid Build Coastguard Worker     *error_msg = strdup(exported_ns.error().message().c_str());
576*795d594fSAndroid Build Coastguard Worker     return;
577*795d594fSAndroid Build Coastguard Worker   }
578*795d594fSAndroid Build Coastguard Worker 
579*795d594fSAndroid Build Coastguard Worker   Result<void> linked = ns->Link(&exported_ns.value(), std::string(library_name));
580*795d594fSAndroid Build Coastguard Worker   if (!linked.ok()) {
581*795d594fSAndroid Build Coastguard Worker     *error_msg = strdup(linked.error().message().c_str());
582*795d594fSAndroid Build Coastguard Worker   }
583*795d594fSAndroid Build Coastguard Worker }
584*795d594fSAndroid Build Coastguard Worker 
585*795d594fSAndroid Build Coastguard Worker #endif  // ART_TARGET_ANDROID
586*795d594fSAndroid Build Coastguard Worker 
587*795d594fSAndroid Build Coastguard Worker }  // namespace android
588