diff options
| author | 2019-03-05 00:02:51 +0000 | |
|---|---|---|
| committer | 2019-04-03 11:34:09 +0000 | |
| commit | 7126c5b47d34b9a4d6d7553b8ea48e5085ee6b41 (patch) | |
| tree | eeabacfcf1e75997c2c4755bb84ff63706eba46d /runtime/native/dalvik_system_DexFile.cc | |
| parent | c088b2efe015d49f10597c515a7d749cb0856f84 (diff) | |
Preverify InMemoryDexClassLoader-loaded classes from vdex
This patch creates a new subclass of OatFile - OatFileBackedByVdex -
which initializes OatDexClass instances using the verification info in
a vdex file created by a previous instance of the class loader.
The OatFile is not backed by an actual .oat file.
Bug: 72131483
Test: art/tools/run-libcore-tests.sh
Test: art/test.py -b -r -t 692 -t 693
Change-Id: I3fd055abe17ee9739c07f2e2f4fc2543e4ec8c9e
Diffstat (limited to 'runtime/native/dalvik_system_DexFile.cc')
| -rw-r--r-- | runtime/native/dalvik_system_DexFile.cc | 128 |
1 files changed, 57 insertions, 71 deletions
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index ae1eea5927..eee8cfc620 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -165,6 +165,37 @@ class NullableScopedUtfChars { void operator=(const NullableScopedUtfChars&); }; +static jobject CreateCookieFromOatFileManagerResult( + JNIEnv* env, + std::vector<std::unique_ptr<const DexFile>>& dex_files, + const OatFile* oat_file, + const std::vector<std::string>& error_msgs) { + ClassLinker* linker = Runtime::Current()->GetClassLinker(); + if (dex_files.empty()) { + ScopedObjectAccess soa(env); + CHECK(!error_msgs.empty()); + // The most important message is at the end. So set up nesting by going forward, which will + // wrap the existing exception as a cause for the following one. + auto it = error_msgs.begin(); + auto itEnd = error_msgs.end(); + for ( ; it != itEnd; ++it) { + ThrowWrappedIOException("%s", it->c_str()); + } + return nullptr; + } + + jlongArray array = ConvertDexFilesToJavaArray(env, oat_file, dex_files); + if (array == nullptr) { + ScopedObjectAccess soa(env); + for (auto& dex_file : dex_files) { + if (linker->IsDexFileRegistered(soa.Self(), *dex_file)) { + dex_file.release(); // NOLINT + } + } + } + return array; +} + static MemMap AllocateDexMemoryMap(JNIEnv* env, jint start, jint end) { if (end <= start) { ScopedObjectAccess soa(env); @@ -187,33 +218,6 @@ static MemMap AllocateDexMemoryMap(JNIEnv* env, jint start, jint end) { return dex_mem_map; } -static const DexFile* CreateDexFile(JNIEnv* env, MemMap&& dex_mem_map) { - std::string location = StringPrintf("Anonymous-DexFile@%p-%p", - dex_mem_map.Begin(), - dex_mem_map.End()); - std::string error_message; - const ArtDexFileLoader dex_file_loader; - std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(location, - 0, - std::move(dex_mem_map), - /* verify= */ true, - /* verify_checksum= */ true, - &error_message)); - if (dex_file == nullptr) { - ScopedObjectAccess soa(env); - ThrowWrappedIOException("%s", error_message.c_str()); - return nullptr; - } - - if (!dex_file->DisableWrite()) { - ScopedObjectAccess soa(env); - ThrowWrappedIOException("Failed to make dex file read-only"); - return nullptr; - } - - return dex_file.release(); -} - struct ScopedIntArrayAccessor { public: ScopedIntArrayAccessor(JNIEnv* env, jintArray arr) : env_(env), array_(arr) { @@ -238,7 +242,9 @@ static jobject DexFile_openInMemoryDexFilesNative(JNIEnv* env, jobjectArray buffers, jobjectArray arrays, jintArray jstarts, - jintArray jends) { + jintArray jends, + jobject class_loader, + jobjectArray dex_elements) { jsize buffers_length = env->GetArrayLength(buffers); CHECK_EQ(buffers_length, env->GetArrayLength(arrays)); CHECK_EQ(buffers_length, env->GetArrayLength(jstarts)); @@ -248,8 +254,8 @@ static jobject DexFile_openInMemoryDexFilesNative(JNIEnv* env, ScopedIntArrayAccessor ends(env, jends); // Allocate memory for dex files and copy data from ByteBuffers. - std::vector<std::unique_ptr<const DexFile>> dex_files; - dex_files.reserve(buffers_length); + std::vector<MemMap> dex_mem_maps; + dex_mem_maps.reserve(buffers_length); for (jsize i = 0; i < buffers_length; ++i) { jobject buffer = env->GetObjectArrayElement(buffers, i); jbyteArray array = reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(arrays, i)); @@ -278,15 +284,20 @@ static jobject DexFile_openInMemoryDexFilesNative(JNIEnv* env, env->GetByteArrayRegion(array, start, end - start, destination); } - std::unique_ptr<const DexFile> dex_file(CreateDexFile(env, std::move(dex_data))); - if (dex_file == nullptr) { - DCHECK(env->ExceptionCheck()); - return nullptr; - } - dex_files.push_back(std::move(dex_file)); + dex_mem_maps.push_back(std::move(dex_data)); } - return ConvertDexFilesToJavaArray(env, /* oat_file= */ nullptr, dex_files); + // Hand MemMaps over to OatFileManager to open the dex files and potentially + // create a backing OatFile instance from an anonymous vdex. + std::vector<std::string> error_msgs; + const OatFile* oat_file = nullptr; + std::vector<std::unique_ptr<const DexFile>> dex_files = + Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(std::move(dex_mem_maps), + class_loader, + dex_elements, + /*out*/ &oat_file, + /*out*/ &error_msgs); + return CreateCookieFromOatFileManagerResult(env, dex_files, oat_file, error_msgs); } // TODO(calin): clean up the unused parameters (here and in libcore). @@ -302,42 +313,15 @@ static jobject DexFile_openDexFileNative(JNIEnv* env, return nullptr; } - Runtime* const runtime = Runtime::Current(); - ClassLinker* linker = runtime->GetClassLinker(); - std::vector<std::unique_ptr<const DexFile>> dex_files; std::vector<std::string> error_msgs; const OatFile* oat_file = nullptr; - - dex_files = runtime->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(), - class_loader, - dex_elements, - /*out*/ &oat_file, - /*out*/ &error_msgs); - - if (!dex_files.empty()) { - jlongArray array = ConvertDexFilesToJavaArray(env, oat_file, dex_files); - if (array == nullptr) { - ScopedObjectAccess soa(env); - for (auto& dex_file : dex_files) { - if (linker->IsDexFileRegistered(soa.Self(), *dex_file)) { - dex_file.release(); // NOLINT - } - } - } - return array; - } else { - ScopedObjectAccess soa(env); - CHECK(!error_msgs.empty()); - // The most important message is at the end. So set up nesting by going forward, which will - // wrap the existing exception as a cause for the following one. - auto it = error_msgs.begin(); - auto itEnd = error_msgs.end(); - for ( ; it != itEnd; ++it) { - ThrowWrappedIOException("%s", it->c_str()); - } - - return nullptr; - } + std::vector<std::unique_ptr<const DexFile>> dex_files = + Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(), + class_loader, + dex_elements, + /*out*/ &oat_file, + /*out*/ &error_msgs); + return CreateCookieFromOatFileManagerResult(env, dex_files, oat_file, error_msgs); } static jstring DexFile_getClassLoaderContext(JNIEnv* env, @@ -938,6 +922,8 @@ static JNINativeMethod gMethods[] = { "[[B" "[I" "[I" + "Ljava/lang/ClassLoader;" + "[Ldalvik/system/DexPathList$Element;" ")Ljava/lang/Object;"), NATIVE_METHOD(DexFile, getClassLoaderContext, "(Ljava/lang/ClassLoader;" |