simplify renderscript .so duplicate handling
When renderscript loads a shared library, it first checks to see if the
shared library is already loaded. If the library is already loaded,
renderscript creates a copy of the shared library, loads it, then
immediately deletes that copy. This ensures that renderscript doesn't
end up aliasing global data between the various Script instances (which
are supposed to be completely independent).
This has a few disadvantages:
1) Copying data involves disk I/O and could be slow.
2) Copying data results in unnecessary flash wear.
3) Copying data inhibits page sharing / caching.
4) Copying data makes the code more complicated than necessary.
5) Copying data complicates security hardening.
For framework code, use functionality provided by the
Android dynamic linker to avoid global symbol conflicts. This avoids
the excess copying while still keeping the symbols separate. We retain
the original behavior for the RS support lib (RS_COMPATIBILITY_LIB is
defined), as android_dlopen_ext is only available for devices with API
level 21+.
Testing for global symbol conflict is already present in the
renderscript CTS tests. Please see:
* android.renderscript.cts.ComputeTest#testInstance
https://android.googlesource.com/platform/cts/+/f0916664ac55fce2c2d33de48cef87c0ab179030/tests/tests/renderscript/src/android/renderscript/cts/ComputeTest.java#781
* android.renderscript.cts.ScriptGroupTest#testScriptGroupTorture
https://android.googlesource.com/platform/cts/+/f0916664ac55fce2c2d33de48cef87c0ab179030/tests/tests/renderscript/src/android/renderscript/cts/ScriptGroupTest.java#221
Test: cts-tradefed run cts -m CtsRenderscriptTestCases
Bug: 112357170
Change-Id: I878756e1d9c14840f4371a8275cf2cc6e132ea78
diff --git a/cpu_ref/rsCpuExecutable.cpp b/cpu_ref/rsCpuExecutable.cpp
index 12ec908..87c791a 100644
--- a/cpu_ref/rsCpuExecutable.cpp
+++ b/cpu_ref/rsCpuExecutable.cpp
@@ -15,6 +15,7 @@
#include <unistd.h>
#include <dlfcn.h>
+#include <android/dlext.h>
#include <sys/stat.h>
namespace android {
@@ -23,6 +24,7 @@
namespace {
// Check if a path exists and attempt to create it if it doesn't.
+[[maybe_unused]]
static bool ensureCacheDirExists(const char *path) {
if (access(path, R_OK | W_OK | X_OK) == 0) {
// Done if we can rwx the directory
@@ -36,6 +38,7 @@
// Copy the file named \p srcFile to \p dstFile.
// Return 0 on success and -1 if anything wasn't copied.
+[[maybe_unused]]
static int copyFile(const char *dstFile, const char *srcFile) {
std::ifstream srcStream(srcFile);
if (!srcStream) {
@@ -249,6 +252,37 @@
return std::string(buf);
}
+static void* loadAsCopy(const char *origName, std::string newName) {
+ void *loaded = nullptr;
+#ifndef RS_COMPATIBILITY_LIB
+ int fd = TEMP_FAILURE_RETRY(open(origName, O_RDONLY | O_CLOEXEC));
+ if (fd == -1) {
+ ALOGE("Unable to open original file %s: %s", origName, strerror(errno));
+ return nullptr;
+ }
+
+ android_dlextinfo extinfo;
+ memset(&extinfo, 0, sizeof(extinfo));
+ extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_FORCE_LOAD;
+ extinfo.library_fd = fd;
+
+ loaded = android_dlopen_ext(newName.c_str(), RTLD_NOW | RTLD_LOCAL, &extinfo);
+ close(fd);
+#else
+ int r = copyFile(newName.c_str(), origName);
+ if (r != 0) {
+ ALOGE("Could not create copy %s -> %s", origName, newName.c_str());
+ return nullptr;
+ }
+ loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
+ r = unlink(newName.c_str());
+ if (r != 0) {
+ ALOGE("Could not unlink copy %s", newName.c_str());
+ }
+#endif // RS_COMPATIBILITY_LIB
+ return loaded;
+}
+
void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDir,
const char *resName, bool *alreadyLoaded) {
// Keep track of which .so libraries have been loaded. Once a library is
@@ -304,16 +338,8 @@
newName.append(getRandomString(6).c_str()); // 62^6 potential filename variants.
newName.append(".so");
- int r = copyFile(newName.c_str(), origName);
- if (r != 0) {
- ALOGE("Could not create copy %s -> %s", origName, newName.c_str());
- return nullptr;
- }
- loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
- r = unlink(newName.c_str());
- if (r != 0) {
- ALOGE("Could not unlink copy %s", newName.c_str());
- }
+ loaded = loadAsCopy(origName, newName);
+
if (loaded) {
LoadedLibraries.insert(newName.c_str());
}