summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Ni <yangni@google.com>2015-06-27 15:45:18 -0700
committerYang Ni <yangni@google.com>2015-06-29 11:33:22 -0700
commit9844cffc8af28c4829012bc0c48f85d04b671f88 (patch)
tree9d9ddcf3ad0db087de76a37d1828f1ee9756f140
parent7427a2546ecfa904cb4e580981f0419c628fc416 (diff)
downloadrs-9844cffc8af28c4829012bc0c48f85d04b671f88.tar.gz
Avoid overwriting shared library file that is open
b/21949580 Writing different contents to an existing .so file, which is currently open, may corrupt its globals and code. Choose a different file name instead. Change-Id: I3e649b09a55b43339283aa1c46f2844c66434c17
-rw-r--r--cpu_ref/rsCpuExecutable.cpp57
-rw-r--r--cpu_ref/rsCpuExecutable.h8
-rw-r--r--cpu_ref/rsCpuScript.cpp11
-rw-r--r--cpu_ref/rsCpuScriptGroup2.cpp47
4 files changed, 86 insertions, 37 deletions
diff --git a/cpu_ref/rsCpuExecutable.cpp b/cpu_ref/rsCpuExecutable.cpp
index e2c27b55..867a2cd6 100644
--- a/cpu_ref/rsCpuExecutable.cpp
+++ b/cpu_ref/rsCpuExecutable.cpp
@@ -20,27 +20,6 @@ namespace renderscript {
namespace {
-// Create a len length string containing random characters from [A-Za-z0-9].
-static std::string getRandomString(size_t len) {
- char buf[len + 1];
- for (size_t i = 0; i < len; i++) {
- uint32_t r = arc4random() & 0xffff;
- r %= 62;
- if (r < 26) {
- // lowercase
- buf[i] = 'a' + r;
- } else if (r < 52) {
- // uppercase
- buf[i] = 'A' + (r - 26);
- } else {
- // Use a number
- buf[i] = '0' + (r - 52);
- }
- }
- buf[len] = '\0';
- return std::string(buf);
-}
-
// Check if a path exists and attempt to create it if it doesn't.
static bool ensureCacheDirExists(const char *path) {
if (access(path, R_OK | W_OK | X_OK) == 0) {
@@ -151,7 +130,8 @@ const char* RsdCpuScriptImpl::BCC_EXE_PATH = "/system/bin/bcc";
void* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir,
const char *resName,
- const char *nativeLibDir) {
+ const char *nativeLibDir,
+ bool* alreadyLoaded) {
void *loaded = nullptr;
#if defined(RS_COMPATIBILITY_LIB) && defined(__LP64__)
@@ -162,7 +142,7 @@ void* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir,
// We should check if we can load the library from the standard app
// location for shared libraries first.
- loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName);
+ loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName, alreadyLoaded);
if (loaded == nullptr) {
ALOGE("Unable to open shared library (%s): %s",
@@ -189,8 +169,28 @@ void* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir,
return loaded;
}
+String8 SharedLibraryUtils::getRandomString(size_t len) {
+ char buf[len + 1];
+ for (size_t i = 0; i < len; i++) {
+ uint32_t r = arc4random() & 0xffff;
+ r %= 62;
+ if (r < 26) {
+ // lowercase
+ buf[i] = 'a' + r;
+ } else if (r < 52) {
+ // uppercase
+ buf[i] = 'A' + (r - 26);
+ } else {
+ // Use a number
+ buf[i] = '0' + (r - 52);
+ }
+ }
+ buf[len] = '\0';
+ return String8(buf);
+}
+
void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDir,
- const char *resName) {
+ const char *resName, bool *alreadyLoaded) {
// Keep track of which .so libraries have been loaded. Once a library is
// in the set (per-process granularity), we must instead make a copy of
// the original shared object (randomly named .so file) and load that one
@@ -208,6 +208,9 @@ void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDi
// Common path is that we have not loaded this Script/library before.
if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
+ if (alreadyLoaded != nullptr) {
+ *alreadyLoaded = false;
+ }
loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL);
if (loaded) {
LoadedLibraries.insert(origName);
@@ -215,6 +218,10 @@ void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDi
return loaded;
}
+ if (alreadyLoaded != nullptr) {
+ *alreadyLoaded = true;
+ }
+
std::string newName(cacheDir);
// Append RS_CACHE_DIR only if it is not found in cacheDir
@@ -234,7 +241,7 @@ void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDi
newName.append("librs.");
newName.append(resName);
newName.append("#");
- newName.append(getRandomString(6)); // 62^6 potential filename variants.
+ newName.append(getRandomString(6).string()); // 62^6 potential filename variants.
newName.append(".so");
int r = copyFile(newName.c_str(), origName);
diff --git a/cpu_ref/rsCpuExecutable.h b/cpu_ref/rsCpuExecutable.h
index 0464dacd..68809706 100644
--- a/cpu_ref/rsCpuExecutable.h
+++ b/cpu_ref/rsCpuExecutable.h
@@ -43,14 +43,18 @@ public:
// For 64bit RS Support Lib, the shared lib path cannot be constructed from
// cacheDir, so nativeLibDir is needed to load shared libs.
static void* loadSharedLibrary(const char *cacheDir, const char *resName,
- const char *nativeLibDir = nullptr);
+ const char *nativeLibDir = nullptr,
+ bool *alreadyLoaded = nullptr);
+
+ // Create a len length string containing random characters from [A-Za-z0-9].
+ static String8 getRandomString(size_t len);
private:
// Attempt to load the shared library from origName, but then fall back to
// creating a copy of the shared library if necessary (to ensure instancing).
// This function returns the dlopen()-ed handle if successful.
static void *loadSOHelper(const char *origName, const char *cacheDir,
- const char *resName);
+ const char *resName, bool* alreadyLoaded = nullptr);
static const char* LD_EXE_PATH;
static const char* RS_CACHE_DIR;
diff --git a/cpu_ref/rsCpuScript.cpp b/cpu_ref/rsCpuScript.cpp
index ea577bc8..bfed1f5a 100644
--- a/cpu_ref/rsCpuScript.cpp
+++ b/cpu_ref/rsCpuScript.cpp
@@ -883,15 +883,12 @@ const char* RsdCpuScriptImpl::getFieldName(uint32_t slot) const {
RsdCpuScriptImpl::~RsdCpuScriptImpl() {
#ifndef RS_COMPATIBILITY_LIB
- if (mCompilerDriver) {
- delete mCompilerDriver;
- }
+ delete mCompilerDriver;
#endif
- if (mScriptExec != nullptr) {
- delete mScriptExec;
- }
- if (mBoundAllocs) delete[] mBoundAllocs;
+ delete mScriptExec;
+
+ delete[] mBoundAllocs;
if (mScriptSO) {
dlclose(mScriptSO);
}
diff --git a/cpu_ref/rsCpuScriptGroup2.cpp b/cpu_ref/rsCpuScriptGroup2.cpp
index 8923c651..bf014031 100644
--- a/cpu_ref/rsCpuScriptGroup2.cpp
+++ b/cpu_ref/rsCpuScriptGroup2.cpp
@@ -156,6 +156,7 @@ CpuScriptGroup2Impl::CpuScriptGroup2Impl(RsdCpuReferenceImpl *cpuRefImpl,
mExecutable(nullptr), mScriptObj(nullptr) {
rsAssert(!mGroup->mClosures.empty());
+ mCpuRefImpl->lockMutex();
Batch* batch = new Batch(this, "Batch0");
int i = 0;
for (Closure* closure: mGroup->mClosures) {
@@ -192,6 +193,7 @@ CpuScriptGroup2Impl::CpuScriptGroup2Impl(RsdCpuReferenceImpl *cpuRefImpl,
}
}
#endif // RS_COMPATIBILITY_LIB
+ mCpuRefImpl->unlockMutex();
}
void Batch::resolveFuncPtr(void* sharedObj) {
@@ -279,6 +281,9 @@ void setupCompileArguments(
}
args->push_back("-output_path");
args->push_back(outputDir);
+
+ // The output filename has to be the last, in case we need to pop it out and
+ // replace with a different name.
args->push_back("-o");
args->push_back(outputFileName);
}
@@ -396,15 +401,41 @@ void CpuScriptGroup2Impl::compile(const char* cacheDir) {
// Try to load a shared lib from code cache matching filename and checksum
//===--------------------------------------------------------------------===//
- mScriptObj = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName);
+ bool alreadyLoaded = false;
+ std::string cloneName;
+
+ mScriptObj = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName, nullptr,
+ &alreadyLoaded);
if (mScriptObj != nullptr) {
+ // A shared library named resName is found in code cache directory
+ // cacheDir, and loaded with the handle stored in mScriptObj.
+
mExecutable = ScriptExecutable::createFromSharedObject(
getCpuRefImpl()->getContext(), mScriptObj, checksum);
+
if (mExecutable != nullptr) {
+ // The loaded shared library in mScriptObj has a matching checksum.
+ // An executable object has been created.
return;
- } else {
- ALOGE("Failed to create an executable object from so file");
}
+
+ ALOGV("Failed to create an executable object from so file due to "
+ "mismatching checksum");
+
+ if (alreadyLoaded) {
+ // The shared object found in code cache has already been loaded.
+ // A different file name is needed for the new shared library, to
+ // avoid corrupting the currently loaded instance.
+
+ cloneName.append(resName);
+ cloneName.append("#");
+ cloneName.append(SharedLibraryUtils::getRandomString(6).string());
+
+ // The last element in arguments is the output filename.
+ arguments.pop_back();
+ arguments.push_back(cloneName.c_str());
+ }
+
dlclose(mScriptObj);
mScriptObj = nullptr;
}
@@ -443,6 +474,16 @@ void CpuScriptGroup2Impl::compile(const char* cacheDir) {
return;
}
+ if (alreadyLoaded) {
+ // Delete the temporary, random-named file that we created to avoid
+ // interfering with an already loaded shared library.
+ string cloneFilePath(cacheDir);
+ cloneFilePath.append("/");
+ cloneFilePath.append(cloneName.c_str());
+ cloneFilePath.append(".so");
+ unlink(cloneFilePath.c_str());
+ }
+
mExecutable = ScriptExecutable::createFromSharedObject(
getCpuRefImpl()->getContext(),
mScriptObj);