diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-02-14 07:49:36 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-02-14 07:49:36 +0000 |
commit | 89cc90b242351416b1c2a952721381e7186dfe28 (patch) | |
tree | c820706e3e7f1033fa6c11a8369e7d276e6de5ec | |
parent | b91a6ee768980d244dbfc3ae7a90122ff7330a7d (diff) | |
parent | c4be0fcab2f88a629251a38fd2ff20e1e604e20f (diff) | |
download | art-android12-mainline-ipsec-release.tar.gz |
Snap for 8180713 from c4be0fcab2f88a629251a38fd2ff20e1e604e20f to mainline-ipsec-releaseandroid-mainline-12.0.0_r88android12-mainline-ipsec-release
Change-Id: I93e46c51436d696339e390205f8a4f1a88b01605
-rw-r--r-- | OWNERS | 3 | ||||
-rw-r--r-- | libartbase/base/file_magic.cc | 4 | ||||
-rw-r--r-- | runtime/gc/space/image_space.cc | 93 | ||||
-rw-r--r-- | runtime/gc/space/image_space.h | 10 | ||||
-rw-r--r-- | test/OWNERS | 1 |
5 files changed, 105 insertions, 6 deletions
@@ -3,13 +3,16 @@ hboehm@google.com jiakaiz@google.com lokeshgidra@google.com mast@google.com +miguelaranda@google.com mingaleev@google.com +mythria@google.com ngeoffray@google.com nikitai@google.com oth@google.com prb@google.com rpl@google.com skvadrik@google.com +solanes@google.com sorinbasca@google.com vichang@google.com vmarko@google.com diff --git a/libartbase/base/file_magic.cc b/libartbase/base/file_magic.cc index 1471c59b73..21b762f6e0 100644 --- a/libartbase/base/file_magic.cc +++ b/libartbase/base/file_magic.cc @@ -44,6 +44,10 @@ File OpenAndReadMagic(const char* filename, uint32_t* magic, std::string* error_ } bool ReadMagicAndReset(int fd, uint32_t* magic, std::string* error_msg) { + if (lseek(fd, 0, SEEK_SET) != 0) { + *error_msg = StringPrintf("Failed to seek to beginning of file : %s", strerror(errno)); + return false; + } int n = TEMP_FAILURE_RETRY(read(fd, magic, sizeof(*magic))); if (n != sizeof(*magic)) { *error_msg = StringPrintf("Failed to find magic"); diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 4eb7f25de0..3a92965114 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -25,7 +25,6 @@ #include "android-base/stringprintf.h" #include "android-base/strings.h" #include "android-base/unique_fd.h" - #include "arch/instruction_set.h" #include "art_field-inl.h" #include "art_method-inl.h" @@ -1503,6 +1502,12 @@ class ImageSpace::BootImageLayout { const char* file_description, /*out*/std::string* error_msg); + bool ValidateOatFile(const std::string& base_location, + const std::string& base_filename, + size_t bcp_index, + size_t component_count, + /*out*/std::string* error_msg); + bool ReadHeader(const std::string& base_location, const std::string& base_filename, size_t bcp_index, @@ -1811,6 +1816,61 @@ bool ImageSpace::BootImageLayout::ValidateHeader(const ImageHeader& header, return true; } +bool ImageSpace::BootImageLayout::ValidateOatFile( + const std::string& base_location, + const std::string& base_filename, + size_t bcp_index, + size_t component_count, + /*out*/std::string* error_msg) { + std::string art_filename = ExpandLocation(base_filename, bcp_index); + std::string art_location = ExpandLocation(base_location, bcp_index); + std::string oat_filename = ImageHeader::GetOatLocationFromImageLocation(art_filename); + std::string oat_location = ImageHeader::GetOatLocationFromImageLocation(art_location); + int oat_fd = -1; + int vdex_fd = -1; + auto dex_filenames = + ArrayRef<const std::string>(boot_class_path_).SubArray(bcp_index, component_count); + auto dex_fds = ArrayRef<const int>(); + // We open the oat file here only for validating that it's up-to-date. We don't open it as + // executable or mmap it to a reserved space. This `OatFile` object will be dropped after + // validation, and will not go into the `ImageSpace`. + std::unique_ptr<OatFile> oat_file; + DCHECK_EQ(oat_fd >= 0, vdex_fd >= 0); + if (oat_fd >= 0) { + oat_file.reset(OatFile::Open( + /*zip_fd=*/ -1, + vdex_fd, + oat_fd, + oat_location, + /*executable=*/ false, + /*low_4gb=*/ false, + dex_filenames, + /*reservation=*/ nullptr, + error_msg)); + } else { + oat_file.reset(OatFile::Open( + /*zip_fd=*/ -1, + oat_filename, + oat_location, + /*executable=*/ false, + /*low_4gb=*/ false, + dex_filenames, + /*reservation=*/ nullptr, + error_msg)); + } + if (oat_file == nullptr) { + *error_msg = StringPrintf("Failed to open oat file '%s' when validating it for image '%s': %s", + oat_filename.c_str(), + art_location.c_str(), + error_msg->c_str()); + return false; + } + if (!ImageSpace::ValidateOatFile(*oat_file, error_msg, dex_filenames, dex_fds)) { + return false; + } + return true; +} + bool ImageSpace::BootImageLayout::ReadHeader(const std::string& base_location, const std::string& base_filename, size_t bcp_index, @@ -1828,6 +1888,15 @@ bool ImageSpace::BootImageLayout::ReadHeader(const std::string& base_location, return false; } + // Validate oat files. We do it here so that the boot image will be re-compiled in memory if it's + // outdated. + size_t component_count = (header.GetImageSpaceCount() == 1u) ? header.GetComponentCount() : 1u; + for (size_t i = 0; i < header.GetImageSpaceCount(); i++) { + if (!ValidateOatFile(base_location, base_filename, bcp_index + i, component_count, error_msg)) { + return false; + } + } + if (chunks_.empty()) { base_address_ = reinterpret_cast32<uint32_t>(header.GetImageBegin()); } @@ -3120,6 +3189,8 @@ bool ImageSpace::BootImageLoader::LoadFromSystem( return false; } + // Load the image. We don't validate oat files in this stage because they have been validated + // before. if (!LoadImage(layout, /*validate_oat_file=*/ false, extra_reservation_size, @@ -3268,20 +3339,32 @@ void ImageSpace::Dump(std::ostream& os) const { } bool ImageSpace::ValidateOatFile(const OatFile& oat_file, std::string* error_msg) { + return ValidateOatFile(oat_file, error_msg, ArrayRef<const std::string>(), ArrayRef<const int>()); +} + +bool ImageSpace::ValidateOatFile(const OatFile& oat_file, + std::string* error_msg, + ArrayRef<const std::string> dex_filenames, + ArrayRef<const int> dex_fds) { const ArtDexFileLoader dex_file_loader; + size_t dex_file_index = 0; for (const OatDexFile* oat_dex_file : oat_file.GetOatDexFiles()) { - const std::string& dex_file_location = oat_dex_file->GetDexFileLocation(); - // Skip multidex locations - These will be checked when we visit their // corresponding primary non-multidex location. - if (DexFileLoader::IsMultiDexLocation(dex_file_location.c_str())) { + if (DexFileLoader::IsMultiDexLocation(oat_dex_file->GetDexFileLocation().c_str())) { continue; } + DCHECK(dex_filenames.empty() || dex_file_index < dex_filenames.size()); + const std::string& dex_file_location = + dex_filenames.empty() ? oat_dex_file->GetDexFileLocation() : dex_filenames[dex_file_index]; + int dex_fd = dex_file_index < dex_fds.size() ? dex_fds[dex_file_index] : -1; + dex_file_index++; + std::vector<uint32_t> checksums; std::vector<std::string> dex_locations_ignored; if (!dex_file_loader.GetMultiDexChecksums( - dex_file_location.c_str(), &checksums, &dex_locations_ignored, error_msg)) { + dex_file_location.c_str(), &checksums, &dex_locations_ignored, error_msg, dex_fd)) { *error_msg = StringPrintf("ValidateOatFile failed to get checksums of dex file '%s' " "referenced by oat file %s: %s", dex_file_location.c_str(), diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h index 545f659c68..350b9883bb 100644 --- a/runtime/gc/space/image_space.h +++ b/runtime/gc/space/image_space.h @@ -266,6 +266,16 @@ class ImageSpace : public MemMapSpace { // This function is exposed for testing purposes. static bool ValidateOatFile(const OatFile& oat_file, std::string* error_msg); + // Same as above, but allows to use `dex_filenames` and `dex_fds` to find the dex files instead of + // using the dex filenames in the header of the oat file. This overload is useful when the actual + // dex filenames are different from what's in the header (e.g., when we run dex2oat on host), or + // when the runtime can only access files through FDs (e.g., when we run dex2oat on target in a + // restricted SELinux domain). + static bool ValidateOatFile(const OatFile& oat_file, + std::string* error_msg, + ArrayRef<const std::string> dex_filenames, + ArrayRef<const int> dex_fds); + // Return the end of the image which includes non-heap objects such as ArtMethods and ArtFields. uint8_t* GetImageEnd() const { return Begin() + GetImageHeader().GetImageSize(); diff --git a/test/OWNERS b/test/OWNERS index 28d5064aff..7d11748d44 100644 --- a/test/OWNERS +++ b/test/OWNERS @@ -1,4 +1,3 @@ # See also ART owners in the parent directory. rpl@google.com dsrbecky@google.com -* |