1 /*
2  * Copyright (C) 2023 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 "native_bridge.h"
18 
19 #include <dlfcn.h>
20 #include <libgen.h>
21 #include <stdio.h>
22 #include <sys/system_properties.h>
23 
24 #include <deque>
25 #include <map>
26 #include <mutex>
27 #include <set>
28 #include <string>
29 #include <string_view>
30 
31 #include "procinfo/process_map.h"
32 
33 #include "berberis/base/algorithm.h"
34 #include "berberis/base/bit_util.h"
35 #include "berberis/base/config_globals.h"
36 #include "berberis/base/file.h"
37 #include "berberis/base/logging.h"
38 #include "berberis/base/strings.h"
39 #include "berberis/base/tracing.h"
40 #include "berberis/guest_abi/guest_call.h"
41 #include "berberis/guest_loader/guest_loader.h"
42 #include "berberis/guest_os_primitives/guest_map_shadow.h"
43 #include "berberis/guest_state/guest_addr.h"
44 #include "berberis/jni/jni_trampolines.h"
45 #include "berberis/native_activity/native_activity_wrapper.h"
46 #include "berberis/native_bridge/native_bridge.h"
47 #include "berberis/runtime/berberis.h"
48 #include "berberis/runtime_primitives/known_guest_function_wrapper.h"
49 
50 #define LOG_NB ALOGV  // redefine to ALOGD for debugging
51 
52 extern "C" {
53 
54 // Extended android loader functions for namespace management
55 
56 bool android_init_anonymous_namespace(const char* shared_libs_sonames,
57                                       const char* library_search_path);
58 
59 struct android_namespace_t* android_create_namespace(const char* name,
60                                                      const char* ld_library_path,
61                                                      const char* default_library_path,
62                                                      uint64_t type,
63                                                      const char* permitted_when_isolated_path,
64                                                      struct android_namespace_t* parent);
65 
66 bool android_link_namespaces(struct android_namespace_t* from,
67                              struct android_namespace_t* to,
68                              const char* shared_libs_sonames);
69 
70 struct android_namespace_t* android_get_exported_namespace(const char* name);
71 
72 }  // extern "C"
73 
74 namespace android {
75 
76 // We maintain host namespace here to provide ability to open host
77 // libraries via native bridge. See http://b/308371292 for details.
78 struct native_bridge_namespace_t {
79   android_namespace_t* guest_namespace;
80   android_namespace_t* host_namespace;
81 };
82 
83 }  // namespace android
84 
85 namespace {
86 
87 // See android/system/core/libnativebridge/native_bridge.cc
88 // Even thought berberis does not support early version of NB interface
89 // (deprecated methods do not work anymore) v2 support is needed to have NB call
90 // getSignalHandler function.
91 const constexpr uint32_t kNativeBridgeCallbackMinVersion = 2;
92 const constexpr uint32_t kNativeBridgeCallbackVersion = 7;
93 const constexpr uint32_t kNativeBridgeCallbackMaxVersion = kNativeBridgeCallbackVersion;
94 
95 const android::NativeBridgeRuntimeCallbacks* g_runtime_callbacks = nullptr;
96 
97 using native_bridge_namespace_t = android::native_bridge_namespace_t;
98 using GuestAddr = berberis::GuestAddr;
99 
100 // Treble uses "sphal" name for the vendor namespace.
101 constexpr const char* kVendorNamespaceName = "sphal";
102 
103 class NdktNativeBridge {
104  public:
105   NdktNativeBridge();
106   ~NdktNativeBridge();
107 
108   bool Initialize(std::string* error_msg);
109   void* LoadLibrary(const char* libpath, int flags, const native_bridge_namespace_t* ns = nullptr);
110   void* LoadGuestLibrary(const char* libpath,
111                          int flags,
112                          const native_bridge_namespace_t* ns = nullptr);
113   GuestAddr DlSym(void* handle, const char* name);
114   const char* DlError();
115   bool InitAnonymousNamespace(const char* public_ns_sonames, const char* anon_ns_library_path);
116   native_bridge_namespace_t* CreateNamespace(const char* name,
117                                              const char* ld_library_path,
118                                              const char* default_library_path,
119                                              uint64_t type,
120                                              const char* permitted_when_isolated_path,
121                                              native_bridge_namespace_t* parent_ns);
122   native_bridge_namespace_t* GetExportedNamespace(const char* name);
123   bool LinkNamespaces(native_bridge_namespace_t* from,
124                       native_bridge_namespace_t* to,
125                       const char* shared_libs_sonames);
126 
127   bool IsHostHandle(void* handle) const;
128 
129  private:
130   bool FinalizeInit();
131   native_bridge_namespace_t* CreateNativeBridgeNamespace(android_namespace_t* host_namespace,
132                                                          android_namespace_t* guest_namespace);
133   void AddHostLibrary(void* handle);
134 
135   berberis::GuestLoader* guest_loader_;
136 
137   mutable std::mutex host_libraries_lock_;
138   std::set<void*> host_libraries_;
139 
140   std::mutex namespaces_lock_;
141   std::deque<native_bridge_namespace_t> namespaces_;
142   std::map<std::string, native_bridge_namespace_t> exported_namespaces_;
143 };
144 
NdktNativeBridge()145 NdktNativeBridge::NdktNativeBridge() : guest_loader_(nullptr) {}
146 
~NdktNativeBridge()147 NdktNativeBridge::~NdktNativeBridge() {}
148 
Initialize(std::string * error_msg)149 bool NdktNativeBridge::Initialize(std::string* error_msg) {
150   guest_loader_ = berberis::GuestLoader::StartAppProcessInNewThread(error_msg);
151   berberis::RegisterKnownGuestFunctionWrapper("JNI_OnLoad", berberis::WrapGuestJNIOnLoad);
152   berberis::RegisterKnownGuestFunctionWrapper("ANativeActivity_onCreate",
153                                               berberis::WrapGuestNativeActivityOnCreate);
154   return guest_loader_ != nullptr;
155 }
156 
LoadLibrary(const char * libpath,int flags,const native_bridge_namespace_t * ns)157 void* NdktNativeBridge::LoadLibrary(const char* libpath,
158                                     int flags,
159                                     const native_bridge_namespace_t* ns) {
160   // We don't have a callback after all java initialization is finished. So we call the finalizing
161   // routine from here, just before we load any app's native code.
162   static bool init_finalized = FinalizeInit();
163   UNUSED(init_finalized);
164 
165   void* handle = LoadGuestLibrary(libpath, flags, ns);
166   if (handle != nullptr) {
167     return handle;
168   }
169 
170   // http://b/206676167: Do not fallback to host for libRS.so
171   if (berberis::Basename(libpath) == "libRS.so") {
172     return handle;
173   }
174 
175   // Try falling back to host loader.
176   android_dlextinfo extinfo_holder;
177   android_dlextinfo* extinfo = nullptr;
178 
179   if (ns != nullptr) {
180     extinfo_holder.flags = ANDROID_DLEXT_USE_NAMESPACE;
181     extinfo_holder.library_namespace = ns->host_namespace;
182     extinfo = &extinfo_holder;
183   }
184 
185   handle = android_dlopen_ext(libpath, flags, extinfo);
186   if (handle != nullptr) {
187     ALOGI("'%s' library was loaded for the host platform.", libpath);
188     AddHostLibrary(handle);
189   }
190 
191   return handle;
192 }
193 
LoadGuestLibrary(const char * libpath,int flags,const native_bridge_namespace_t * ns)194 void* NdktNativeBridge::LoadGuestLibrary(const char* libpath,
195                                          int flags,
196                                          const native_bridge_namespace_t* ns) {
197   android_dlextinfo extinfo_holder;
198   android_dlextinfo* extinfo = nullptr;
199 
200   if (ns != nullptr) {
201     extinfo_holder.flags = ANDROID_DLEXT_USE_NAMESPACE;
202     extinfo_holder.library_namespace = ns->guest_namespace;
203     extinfo = &extinfo_holder;
204   }
205 
206   return guest_loader_->DlOpenExt(libpath, flags, extinfo);
207 }
208 
AddHostLibrary(void * handle)209 void NdktNativeBridge::AddHostLibrary(void* handle) {
210   const std::lock_guard<std::mutex> guard(host_libraries_lock_);
211   host_libraries_.insert(handle);
212 }
213 
IsHostHandle(void * handle) const214 bool NdktNativeBridge::IsHostHandle(void* handle) const {
215   const std::lock_guard<std::mutex> guard(host_libraries_lock_);
216   return berberis::Contains(host_libraries_, handle);
217 }
218 
DlSym(void * handle,const char * name)219 GuestAddr NdktNativeBridge::DlSym(void* handle, const char* name) {
220   CHECK(!IsHostHandle(handle));
221   return guest_loader_->DlSym(handle, name);
222 }
223 
DlError()224 const char* NdktNativeBridge::DlError() {
225   // There is no good way of knowing where the error happened, - prioritize the guest loader.
226   const char* error = guest_loader_->DlError();
227   if (error != nullptr) {
228     return error;
229   }
230 
231   return dlerror();
232 }
233 
CreateNamespace(const char * name,const char * ld_library_path,const char * default_library_path,uint64_t type,const char * permitted_when_isolated_path,native_bridge_namespace_t * parent_ns)234 native_bridge_namespace_t* NdktNativeBridge::CreateNamespace(
235     const char* name,
236     const char* ld_library_path,
237     const char* default_library_path,
238     uint64_t type,
239     const char* permitted_when_isolated_path,
240     native_bridge_namespace_t* parent_ns) {
241   // Android SDK libraries do not have a good mechanism for using JNI libraries.
242   // The only way to make it work is to put them to system search path and make
243   // the library public (visible from apps). See http://b/308371292 for details.
244   //
245   // Since `ClassLoader.findLibrary` is looking for the library in 'java.library.path'
246   // in addition to paths used here it is able to find a JNI library located in system
247   // library path. If then such a library appears to be a public library, the android
248   // loader will be able to load it from the system linker namespace.
249   //
250   // It could also happen so that the app puts different architecture libraries
251   // in the same folder (say x86_64 libraries to arm64 folder), in which case
252   // they will work if the architecture happens to match with host one. This is
253   // why we preserve guest search path for the host namespace.
254   auto* host_namespace = android_create_namespace(name,
255                                                   ld_library_path,
256                                                   default_library_path,
257                                                   type,
258                                                   permitted_when_isolated_path,
259                                                   parent_ns->host_namespace);
260 
261   auto* guest_namespace = guest_loader_->CreateNamespace(name,
262                                                          ld_library_path,
263                                                          default_library_path,
264                                                          type,
265                                                          permitted_when_isolated_path,
266                                                          parent_ns->guest_namespace);
267 
268   return CreateNativeBridgeNamespace(host_namespace, guest_namespace);
269 }
270 
GetExportedNamespace(const char * name)271 native_bridge_namespace_t* NdktNativeBridge::GetExportedNamespace(const char* name) {
272   const std::lock_guard<std::mutex> guard(namespaces_lock_);
273   auto it = exported_namespaces_.find(name);
274   if (it != exported_namespaces_.end()) {
275     return &it->second;
276   }
277 
278   auto host_namespace = android_get_exported_namespace(name);
279   auto guest_namespace = guest_loader_->GetExportedNamespace(name);
280 
281   auto [insert_it, inserted] =
282       exported_namespaces_.try_emplace(std::string(name),
283                                        native_bridge_namespace_t{.guest_namespace = guest_namespace,
284                                                                  .host_namespace = host_namespace});
285   CHECK(inserted);
286 
287   return &insert_it->second;
288 }
289 
InitAnonymousNamespace(const char * public_ns_sonames,const char * anon_ns_library_path)290 bool NdktNativeBridge::InitAnonymousNamespace(const char* public_ns_sonames,
291                                               const char* anon_ns_library_path) {
292   return guest_loader_->InitAnonymousNamespace(public_ns_sonames, anon_ns_library_path) &&
293          android_init_anonymous_namespace(public_ns_sonames, anon_ns_library_path);
294 }
295 
LinkNamespaces(native_bridge_namespace_t * from,native_bridge_namespace_t * to,const char * shared_libs_sonames)296 bool NdktNativeBridge::LinkNamespaces(native_bridge_namespace_t* from,
297                                       native_bridge_namespace_t* to,
298                                       const char* shared_libs_sonames) {
299   return guest_loader_->LinkNamespaces(
300              from->guest_namespace, to->guest_namespace, shared_libs_sonames) &&
301          android_link_namespaces(from->host_namespace, to->host_namespace, shared_libs_sonames);
302 }
303 
CreateNativeBridgeNamespace(android_namespace_t * host_namespace,android_namespace_t * guest_namespace)304 native_bridge_namespace_t* NdktNativeBridge::CreateNativeBridgeNamespace(
305     android_namespace_t* host_namespace,
306     android_namespace_t* guest_namespace) {
307   const std::lock_guard<std::mutex> guard(namespaces_lock_);
308   namespaces_.emplace_back(native_bridge_namespace_t{.guest_namespace = guest_namespace,
309                                                      .host_namespace = host_namespace});
310   return &namespaces_.back();
311 }
312 
ProtectMappingsFromGuest()313 void ProtectMappingsFromGuest() {
314   auto callback =
315       [](uint64_t start, uint64_t end, uint16_t, uint64_t, ino_t, const char* libname_c_str, bool) {
316         std::string_view libname(libname_c_str);
317         // Per analysis in b/218772975 only libc is affected. It's occasionally either proxy libc or
318         // guest libc. So we protect all libs with "libc.so" substring. At this point no app's libs
319         // are loaded yet, so the app shouldn't tamper with the already loaded ones. We don't
320         // protect all the already loaded libraries though since GuestMapShadow isn't optimized
321         // to work with large number of entries. Also some of them could be unmapped later, which is
322         // not expected for libc.so.
323         if (libname.find("libc.so") != std::string_view::npos) {
324           berberis::GuestMapShadow::GetInstance()->AddProtectedMapping(
325               berberis::bit_cast<void*>(static_cast<uintptr_t>(start)),
326               berberis::bit_cast<void*>(static_cast<uintptr_t>(end)));
327         }
328       };
329   android::procinfo::ReadMapFile("/proc/self/maps", callback);
330 }
331 
332 extern "C" const char* __progname;
333 
FinalizeInit()334 bool NdktNativeBridge::FinalizeInit() {
335   // Guest-libc is expected to be loaded along with app-process during Initialize(). At that time
336   // __progname isn't yet initialized in java. So now when it should be initialized we copy it over
337   // from host to guest.
338   // Note that we cannot delay Initialize() (and hence guest-libc loading) until now because
339   // guest_loader initialized there is then used to create and link linker namespaces.
340   // We cannot cannot unload (dlclose) guest-libc after app-process loading either (intending to
341   // reload it now to get the updated __progname), since guest_linker is already tightly linked with
342   // it.
343 
344   // Force libc loading if it's not loaded yet to ensure the symbol is overridden.
345   // We do not call LoadLibrary since it'd recurse back into FinalizeInit.
346   void* libc = guest_loader_->DlOpenExt("libc.so", RTLD_NOW, nullptr);
347   CHECK_NE(libc, nullptr);
348   auto addr = DlSym(libc, "__progname");
349   CHECK_NE(addr, berberis::kNullGuestAddr);
350   memcpy(berberis::ToHostAddr<char*>(addr), &__progname, sizeof(__progname));
351 
352   // Now, when guest libc and proxy-libc are loaded,
353   // remember mappings which guest code must not tamper with.
354   ProtectMappingsFromGuest();
355 
356   return true;
357 }
358 
359 NdktNativeBridge g_ndkt_native_bridge;
360 
361 // Runtime values must be non-NULL, otherwise native bridge will be disabled.
362 // Note, that 'supported_abis' and 'abi_count' are deprecated (b/18061712).
GetAppEnvByIsa(const char * app_isa)363 const struct android::NativeBridgeRuntimeValues* GetAppEnvByIsa(const char* app_isa) {
364   if (app_isa == nullptr) {
365     ALOGE("instruction set is null");
366     return nullptr;
367   }
368 
369   if (strcmp(app_isa, berberis::kGuestIsa) == 0) {
370     return &berberis::kNativeBridgeRuntimeValues;
371   }
372 
373   ALOGE("unknown instruction set '%s'", app_isa);
374   return nullptr;
375 }
376 
SetAppPropertiesFromCodeCachePath(const char * private_dir)377 void SetAppPropertiesFromCodeCachePath(const char* private_dir) {
378   if (private_dir == nullptr) {
379     return;
380   }
381 
382   // Expect private_dir to be .../<app_package>/code_cache
383   std::string_view path(private_dir);
384   if (!berberis::ConsumeSuffix(&path, "/code_cache")) {
385     return;
386   }
387 
388   berberis::SetAppPrivateDir(path);
389 
390   auto begin = path.find_last_of('/');
391   if (begin == std::string_view::npos) {
392     return;
393   }
394   berberis::SetAppPackageName(path.substr(begin + 1));
395 }
396 
native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks * runtime_cbs,const char * private_dir,const char * instruction_set)397 bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* runtime_cbs,
398                               const char* private_dir,
399                               const char* instruction_set) {
400   LOG_NB("native_bridge_initialize(runtime_callbacks=%p, private_dir='%s', app_isa='%s')",
401          runtime_cbs,
402          private_dir ? private_dir : "(null)",
403          instruction_set ? instruction_set : "(null)");
404   auto* env = GetAppEnvByIsa(instruction_set);
405   if (env == nullptr) {
406     return false;
407   }
408   g_runtime_callbacks = runtime_cbs;
409   SetAppPropertiesFromCodeCachePath(private_dir);
410   berberis::InitBerberis();
411 
412   char version[PROP_VALUE_MAX];
413   if (__system_property_get("ro.berberis.version", version)) {
414     ALOGI("Initialized Berberis (%s), version %s", env->os_arch, version);
415   } else {
416     ALOGI("Initialized Berberis (%s)", env->os_arch);
417   }
418 
419   std::string error_msg;
420   if (!g_ndkt_native_bridge.Initialize(&error_msg)) {
421     LOG_ALWAYS_FATAL("native_bridge_initialize: %s", error_msg.c_str());
422   }
423   return true;
424 }
425 
native_bridge_loadLibrary(const char * libpath,int flag)426 void* native_bridge_loadLibrary(const char* libpath, int flag) {
427   // We should only get here if this library is not native.
428   LOG_NB("native_bridge_loadLibrary(path='%s', flag=0x%x)", libpath ? libpath : "(null)", flag);
429 
430   return g_ndkt_native_bridge.LoadLibrary(libpath, flag);
431 }
432 
native_bridge_getTrampolineWithJNICallType(void * handle,const char * name,const char * shorty,uint32_t len,enum android::JNICallType jni_call_type)433 void* native_bridge_getTrampolineWithJNICallType(void* handle,
434                                                  const char* name,
435                                                  const char* shorty,
436                                                  uint32_t len,
437                                                  enum android::JNICallType jni_call_type) {
438   LOG_NB(
439       "native_bridge_getTrampolineWithJNICallType(handle=%p, name='%s', shorty='%s', len=%d, "
440       "jni_call_type=%d)",
441       handle,
442       name ? name : "(null)",
443       shorty ? shorty : "(null)",
444       len,
445       jni_call_type);
446 
447   if (g_ndkt_native_bridge.IsHostHandle(handle)) {
448     return dlsym(handle, name);
449   }
450 
451   GuestAddr guest_addr = g_ndkt_native_bridge.DlSym(handle, name);
452   if (!guest_addr) {
453     return nullptr;
454   }
455 
456   if (shorty) {
457     return const_cast<void*>(berberis::WrapGuestJNIFunction(
458         guest_addr,
459         shorty,
460         name,
461         jni_call_type != android::JNICallType::kJNICallTypeCriticalNative));
462   }
463 
464   berberis::HostCode result = berberis::WrapKnownGuestFunction(guest_addr, name);
465   if (result == nullptr) {
466     // No wrapper is registered for this function name.
467     // This usually happens for ANativeActivity_onCreate renamed with android.app.func_name.
468     // TODO(b/27307664): maybe query android.app.func_name from Java and check exactly?
469     TRACE("No wrapper is registered for %s, assume it's ANativeActivity_onCreate", name);
470     result = berberis::WrapKnownGuestFunction(guest_addr, "ANativeActivity_onCreate");
471   }
472   return const_cast<void*>(result);
473 }
474 
native_bridge_getTrampolineForFunctionPointer(const void * method,const char * shorty,uint32_t len,enum android::JNICallType jni_call_type)475 void* native_bridge_getTrampolineForFunctionPointer(const void* method,
476                                                     const char* shorty,
477                                                     uint32_t len,
478                                                     enum android::JNICallType jni_call_type) {
479   LOG_NB(
480       "native_bridge_getTrampolineForFunctionPointer(method=%p, shorty='%s', len=%d, "
481       "jni_call_type=%d)",
482       method,
483       shorty ? shorty : "(null)",
484       len,
485       jni_call_type);
486 
487   auto guest_addr = berberis::ToGuestAddr(method);
488   if (!berberis::GuestMapShadow::GetInstance()->IsExecutable(guest_addr, 1)) {
489     // This is not guest code - happens when native_bridge falls back
490     // to host libraries.
491     return const_cast<void*>(method);
492   }
493 
494   return const_cast<void*>(berberis::WrapGuestJNIFunction(
495       guest_addr,
496       shorty,
497       "(unknown)",
498       jni_call_type != android::JNICallType::kJNICallTypeCriticalNative));
499 }
500 
native_bridge_getTrampoline(void * handle,const char * name,const char * shorty,uint32_t len)501 void* native_bridge_getTrampoline(void* handle,
502                                   const char* name,
503                                   const char* shorty,
504                                   uint32_t len) {
505   LOG_NB(
506       "Warning: Unexpected call to native_bridge_getTrampoline (old android version?), converting "
507       "to a native_bridge_getTrampolineWithJNICallType call with kJNICallTyepRegular");
508   return native_bridge_getTrampolineWithJNICallType(
509       handle, name, shorty, len, android::JNICallType::kJNICallTypeRegular);
510 }
511 
native_bridge_isSupported(const char * libpath)512 bool native_bridge_isSupported(const char* libpath) {
513   LOG_NB("native_bridge_isSupported(path='%s')", libpath ? libpath : "(null)");
514   return true;
515 }
516 
native_bridge_getAppEnv(const char * instruction_set)517 const struct android::NativeBridgeRuntimeValues* native_bridge_getAppEnv(
518     const char* instruction_set) {
519   LOG_NB("native_bridge_getAppEnv(app_isa='%s')", instruction_set ? instruction_set : "(null)");
520   return GetAppEnvByIsa(instruction_set);
521 }
522 
native_bridge_isCompatibleWith(uint32_t bridge_version)523 bool native_bridge_isCompatibleWith(uint32_t bridge_version) {
524   LOG_NB("native_bridge_isCompatibleWith(bridge_version=%d)", bridge_version);
525   return bridge_version >= kNativeBridgeCallbackMinVersion &&
526          bridge_version <= kNativeBridgeCallbackMaxVersion;
527 }
528 
native_bridge_getSignalHandler(int signal)529 android::NativeBridgeSignalHandlerFn native_bridge_getSignalHandler(int signal) {
530   LOG_NB("native_bridge_getSignalHandler(signal=%d)", signal);
531   return nullptr;
532 }
533 
native_bridge_unloadLibrary(void * handle)534 int native_bridge_unloadLibrary(void* handle) {
535   LOG_NB("native_bridge_unloadLibrary(handle=%p)", handle);
536   // TODO(b/276787500): support library unloading!
537   return 0;
538 }
539 
native_bridge_getError()540 const char* native_bridge_getError() {
541   LOG_NB("native_bridge_getError()");
542   return g_ndkt_native_bridge.DlError();
543 }
544 
native_bridge_isPathSupported(const char * library_path)545 bool native_bridge_isPathSupported(const char* library_path) {
546   LOG_NB("native_bridge_isPathSupported(path=%s)", library_path);
547   return strstr(library_path, berberis::kSupportedLibraryPathSubstring) != nullptr;
548 }
549 
native_bridge_initAnonymousNamespace(const char * public_ns_sonames,const char * anon_ns_library_path)550 bool native_bridge_initAnonymousNamespace(const char* public_ns_sonames,
551                                           const char* anon_ns_library_path) {
552   LOG_NB("native_bridge_initAnonymousNamespace(public_ns_sonames=%s, anon_ns_library_path=%s)",
553          public_ns_sonames,
554          anon_ns_library_path);
555   return g_ndkt_native_bridge.InitAnonymousNamespace(public_ns_sonames, anon_ns_library_path);
556 }
557 
native_bridge_createNamespace(const char * name,const char * ld_library_path,const char * default_library_path,uint64_t type,const char * permitted_when_isolated_path,native_bridge_namespace_t * parent_ns)558 native_bridge_namespace_t* native_bridge_createNamespace(const char* name,
559                                                          const char* ld_library_path,
560                                                          const char* default_library_path,
561                                                          uint64_t type,
562                                                          const char* permitted_when_isolated_path,
563                                                          native_bridge_namespace_t* parent_ns) {
564   LOG_NB("native_bridge_createNamespace(name=%s, path=%s)", name, ld_library_path);
565   return g_ndkt_native_bridge.CreateNamespace(
566       name, ld_library_path, default_library_path, type, permitted_when_isolated_path, parent_ns);
567 }
568 
native_bridge_linkNamespaces(native_bridge_namespace_t * from,native_bridge_namespace_t * to,const char * shared_libs_sonames)569 bool native_bridge_linkNamespaces(native_bridge_namespace_t* from,
570                                   native_bridge_namespace_t* to,
571                                   const char* shared_libs_sonames) {
572   LOG_NB("native_bridge_linkNamespaces(from=%p, to=%p, shared_libs=%s)",
573          from,
574          to,
575          shared_libs_sonames);
576 
577   return g_ndkt_native_bridge.LinkNamespaces(from, to, shared_libs_sonames);
578 }
579 
native_bridge_loadLibraryExt(const char * libpath,int flag,native_bridge_namespace_t * ns)580 void* native_bridge_loadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
581   LOG_NB("native_bridge_loadLibraryExt(path=%s)", libpath);
582 
583   return g_ndkt_native_bridge.LoadLibrary(libpath, flag, ns);
584 }
585 
native_bridge_getVendorNamespace()586 native_bridge_namespace_t* native_bridge_getVendorNamespace() {
587   LOG_NB("native_bridge_getVendorNamespace()");
588   // This method is retained for backwards compatibility.
589   return g_ndkt_native_bridge.GetExportedNamespace(kVendorNamespaceName);
590 }
591 
native_bridge_getExportedNamespace(const char * name)592 native_bridge_namespace_t* native_bridge_getExportedNamespace(const char* name) {
593   LOG_NB("native_bridge_getExportedNamespace(name=%s)", name);
594   return g_ndkt_native_bridge.GetExportedNamespace(name);
595 }
596 
native_bridge_preZygoteFork()597 void native_bridge_preZygoteFork() {
598   // In case of app-zygote the translator could have executed some guest code
599   // during app-zygote's doPreload(). Zygote's fork doesn't allow unrecognized
600   // open file descriptors, so we close them.
601   //
602   // We assume that all guest execution has finished in doPreload() and there
603   // are no background guest threads. ART ensures the fork is single-threaded by
604   // calling waitUntilAllThreadsStopped() in ZygoteHooks::preZork().
605   // TODO(b/188923523): Technically this happens after nativePreFork() (which
606   // calls this callback), so theoretically some guest thread may still be
607   // running and finishes later. If this happens to be an issue, we can call an
608   // analog of waitUntilAllThreadsStopped() here. Or try to call nativePreFork()
609   // after waitUntilAllThreadsStopped() in ART.
610 
611   // TODO(b/188923523): Consider moving to berberis::GuestPreZygoteFork().
612   void* liblog = g_ndkt_native_bridge.LoadGuestLibrary("liblog.so", RTLD_NOLOAD);
613   // Nothing to close if the guest library hasn't been loaded.
614   if (liblog) {
615     auto addr = g_ndkt_native_bridge.DlSym(liblog, "__android_log_close");
616     CHECK_NE(addr, berberis::kNullGuestAddr);
617     berberis::GuestCall call;
618     call.RunVoid(addr);
619   }
620 
621   berberis::PreZygoteForkUnsafe();
622 }
623 
624 }  // namespace
625 
626 namespace berberis {
627 
GetJMethodShorty(JNIEnv * env,jmethodID mid)628 const char* GetJMethodShorty(JNIEnv* env, jmethodID mid) {
629   CHECK(g_runtime_callbacks);
630   return (g_runtime_callbacks->getMethodShorty)(env, mid);
631 }
632 
633 }  // namespace berberis
634 
635 extern "C" {
636 // "NativeBridgeItf" is effectively an API (it is the name of the symbol that
637 // will be loaded by the native bridge library).
638 android::NativeBridgeCallbacks NativeBridgeItf = {
639     kNativeBridgeCallbackVersion,
640     &native_bridge_initialize,
641     &native_bridge_loadLibrary,
642     &native_bridge_getTrampoline,
643     &native_bridge_isSupported,
644     &native_bridge_getAppEnv,
645     &native_bridge_isCompatibleWith,
646     &native_bridge_getSignalHandler,
647     &native_bridge_unloadLibrary,
648     &native_bridge_getError,
649     &native_bridge_isPathSupported,
650     &native_bridge_initAnonymousNamespace,
651     &native_bridge_createNamespace,
652     &native_bridge_linkNamespaces,
653     &native_bridge_loadLibraryExt,
654     &native_bridge_getVendorNamespace,
655     &native_bridge_getExportedNamespace,
656     &native_bridge_preZygoteFork,
657     &native_bridge_getTrampolineWithJNICallType,
658     &native_bridge_getTrampolineForFunctionPointer,
659 };
660 }  // extern "C"
661