diff options
author | 2023-02-12 22:22:46 +0000 | |
---|---|---|
committer | 2023-02-13 15:00:42 +0000 | |
commit | 3aab3cf8d13519d4fc21a4c239aa025ec60abe33 (patch) | |
tree | 7aa9f63e086e4112d00bccaa8df072a143f2a78e /runtime/class_linker.cc | |
parent | c0b70bafab8b604ac50f8f7418470ac110a3f71d (diff) |
Fix and re-enable runtime image loading.
We need to store the dex checksums of the dex files being loaded at
runtime, which can be different from the vdex checksums due to compact
dex.
We also need to store the boot classpath and boot classpath checksums,
in the extremely unlikely case the boot image checksum isn't enough.
Test: 845-data-image
Bug: 260557058
Change-Id: I39ca19451ef7a2376f24e631e1867c683f361e3d
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 79 |
1 files changed, 61 insertions, 18 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 08457852a4..32801a2ec9 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -32,6 +32,7 @@ #include <vector> #include "android-base/stringprintf.h" +#include "android-base/strings.h" #include "art_field-inl.h" #include "art_method-inl.h" @@ -2055,30 +2056,72 @@ bool ClassLinker::AddImageSpace( if (special_root == nullptr) { *error_msg = "Unexpected null special root in app image"; return false; - } else if (special_root->IsObjectArray()) { - ObjPtr<mirror::IntArray> checksums = - special_root->AsObjectArray<mirror::Object>()->Get(1)->AsIntArray(); - size_t count = checksums->GetLength(); - if (oat_file->GetVdexFile()->GetNumberOfDexFiles() != count) { + } else if (special_root->IsByteArray()) { + OatHeader* oat_header = reinterpret_cast<OatHeader*>(special_root->AsByteArray()->GetData()); + if (!oat_header->IsValid()) { + *error_msg = "Invalid oat header in special root"; + return false; + } + if (oat_file->GetVdexFile()->GetNumberOfDexFiles() != oat_header->GetDexFileCount()) { *error_msg = "Checksums count does not match"; return false; } - static_assert(sizeof(VdexFile::VdexChecksum) == sizeof(int32_t)); - const VdexFile::VdexChecksum* art_checksums = - reinterpret_cast<VdexFile::VdexChecksum*>(checksums->GetData()); - const VdexFile::VdexChecksum* vdex_checksums = - oat_file->GetVdexFile()->GetDexChecksumsArray(); - if (memcmp(art_checksums, vdex_checksums, sizeof(VdexFile::VdexChecksum) * count) != 0) { - *error_msg = "Image and vdex checksums did not match"; + + // Check if the dex checksums match the dex files that we just loaded. + uint32_t* checksums = reinterpret_cast<uint32_t*>( + reinterpret_cast<uint8_t*>(oat_header) + oat_header->GetHeaderSize()); + for (uint32_t i = 0; i < oat_header->GetDexFileCount(); ++i) { + if (checksums[i] != out_dex_files->at(i)->GetHeader().checksum_) { + *error_msg = "Image and vdex checksums did not match"; + return false; + } + } + + // Validate the class loader context. + const char* stored_context = oat_header->GetStoreValueByKey(OatHeader::kClassPathKey); + if (stored_context == nullptr) { + *error_msg = "Missing class loader context in special root"; return false; } - ObjPtr<mirror::String> encoded_context = - special_root->AsObjectArray<mirror::Object>()->Get(0)->AsString(); - std::string encoded_context_str = encoded_context->ToModifiedUtf8(); - if (context->VerifyClassLoaderContextMatch(encoded_context_str.c_str()) == + if (context->VerifyClassLoaderContextMatch(stored_context) == ClassLoaderContext::VerificationResult::kMismatch) { - *error_msg = - StringPrintf("Class loader contexts don't match: %s", encoded_context_str.c_str()); + *error_msg = StringPrintf("Class loader contexts don't match: %s", stored_context); + return false; + } + + // Validate the apex versions. + if (!gc::space::ImageSpace::ValidateApexVersions(*oat_header, + runtime->GetApexVersions(), + space->GetImageLocation(), + error_msg)) { + return false; + } + + // Validate the boot classpath. + const char* bcp = oat_header->GetStoreValueByKey(OatHeader::kBootClassPathKey); + if (bcp == nullptr) { + *error_msg = "Missing boot classpath in special root"; + return false; + } + std::string runtime_bcp = android::base::Join(runtime->GetBootClassPathLocations(), ':'); + if (strcmp(bcp, runtime_bcp.c_str()) != 0) { + *error_msg = StringPrintf("Mismatch boot classpath: image has %s, runtime has %s", + bcp, + runtime_bcp.c_str()); + return false; + } + + // Validate the dex checksums of the boot classpath. + const char* bcp_checksums = + oat_header->GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey); + if (bcp_checksums == nullptr) { + *error_msg = "Missing boot classpath checksums in special root"; + return false; + } + if (strcmp(bcp_checksums, runtime->GetBootClassPathChecksums().c_str()) != 0) { + *error_msg = StringPrintf("Mismatch boot classpath checksums: image has %s, runtime has %s", + bcp_checksums, + runtime->GetBootClassPathChecksums().c_str()); return false; } } else if (IsBootClassLoader(special_root.Get())) { |