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