summaryrefslogtreecommitdiff
path: root/libnativeloader/native_loader.cpp
diff options
context:
space:
mode:
authorMartin Stjernholm <mast@google.com>2021-04-16 19:55:03 +0100
committerMartin Stjernholm <mast@google.com>2021-05-07 14:53:28 +0000
commit582448f29f2f2529202bf868d00ba5d3d3776bb6 (patch)
tree6e923a08f5d03f1bb6434e27f7ff9076ca4c5302 /libnativeloader/native_loader.cpp
parent39d4df62d4e2606073d05cc363370db825ad7b9f (diff)
Avoid loading external libraries from ARTs internal linker namespace.
dlopen() calls in ART will use its own linker namespace (com_android_art). That's appropriate for internal libraries in the APEX, but not when ART loads libraries on behalf of external requests. In those cases we should instead use android_dlopen_ext to load them from the system namespace, i.e. the one that searches /system/lib(64). The linker config has been using allow_all_shared_libs, so any loads from com_android_art fall back to the system namespace, and hence dlopen() usually works regardless which namespace it ought to use. However we want to drop allow_all_shared_libs, so we need to figure out which dlopen's should use which namespace: 1. Several ART libraries are loaded on-demand, e.g. libart-compiler and libart-disassembler. There are also those going through the runtime plugin system, like libperfetto_hprofd and heapprofd_client_api. All these are internal or at least statically known (so we can provide links for them in the linker config), and should continue to use dlopen from the ART namespace. 2. libnativeloader loads the preloadable public libraries from system/etc/public.libraries.txt, and should use the system namespace for that. 3. libnativebridge loads the native bridge implementation specified through the command line (or ultimately the system property ro.dalvik.vm.native.bridge). It's not part of the ART APEX and not known statically, so the system namespace should be used. 4. libnativeloader also loads JNI libraries from classloader namespaces, but has a fallback if no such namespace can be found based on caller location. Fall back to the system namespace to handle libraries loaded during the preload phase in the zygote. 5. JVMTI agents are loaded by dalvik.system.VMDebug.attachAgent(). Treat these too as external libraries - they are loaded in a way similar to JNI libraries through OpenNativeLibrary in libnativeloader, so are covered by #4. They are normally loaded by apps with a classloader, but a special case is adbconnection which loads libjdwp.so in the ART APEX without one and hence falls back to the system namespace. We therefore need to create a link for it (https://r.android.com/1690889, https://r.android.com/1690795). All cases #2-#5 are covered by libnativeloader and libnativebridge. Introduce OpenSystemLibrary, and since libnativeloader depends on libnativebridge, put it in the latter to be usable from both. It's only an internal dependency not exposed in the APEX stubs. (Another possibility could be to put it in the generic toolbox lib libartbase, but it's split into -d and non-d variants, and we don't want to split libnative{loader,bridge} that way.) Since libnativeloader_test no longer needs to mock dlopen we can simplify it to a more regular test that loads the tested libs dynamically. Test: mmm art Test: atest art/libnativeloader Test: atest CtsJniTestCases Test: Cuttlefish app compat test that uses NDK translation Test: Manual tests with Android Studio TI agents (http://g/art-module-team/7Jy3Tg7LCh0) Bug: 130340935 Change-Id: I2513472c4e1c44f0fcb01a6b4f6eccbb03718f1d
Diffstat (limited to 'libnativeloader/native_loader.cpp')
-rw-r--r--libnativeloader/native_loader.cpp6
1 files changed, 5 insertions, 1 deletions
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index b34692ae16..30c7b5a377 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -254,7 +254,11 @@ void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* pat
}
}
- void* handle = dlopen(path, RTLD_NOW);
+ // Fall back to the system namespace. This happens for preloaded JNI
+ // libraries in the zygote.
+ // TODO(b/185833744): Investigate if this should fall back to the app main
+ // namespace (aka anonymous namespace) instead.
+ void* handle = OpenSystemLibrary(path, RTLD_NOW);
if (handle == nullptr) {
*error_msg = strdup(dlerror());
}