diff options
author | 2023-10-11 12:56:19 +0100 | |
---|---|---|
committer | 2023-10-25 14:17:55 +0000 | |
commit | 876085b17f2bc5efe6b64eee4ddc1be4e967a4f1 (patch) | |
tree | 68c201c1990d300cba2324988c43ce7cfa80f4d4 | |
parent | c13ae9cfc8883372637fb43d2c16b527cd2a5d2a (diff) |
Extend memory range of DexFileContainer passed to Dex loader.
Pass the whole relevant memory range (possibly including some
surrounding non-dex data).
If dex file shares data with other dex files, this will make
it possible to verify that all referred data is within bounds
of valid memory.
Test: ./art/test.py -b --host 001
Change-Id: I5e0058411db4baa3dbe74bfbd7c99d75c9afd694
-rw-r--r-- | dex2oat/linker/oat_writer.cc | 9 | ||||
-rw-r--r-- | libartbase/base/mem_map.cc | 9 | ||||
-rw-r--r-- | libdexfile/dex/dex_file.h | 9 | ||||
-rw-r--r-- | libdexfile/dex/dex_file_loader.cc | 31 | ||||
-rw-r--r-- | libdexfile/dex/dex_file_loader.h | 17 | ||||
-rw-r--r-- | runtime/oat_file.cc | 40 | ||||
-rw-r--r-- | runtime/oat_file.h | 4 | ||||
-rw-r--r-- | runtime/vdex_file.cc | 7 |
8 files changed, 82 insertions, 44 deletions
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index 205b5efde6..5dc070ffdd 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -3114,7 +3114,7 @@ bool OatWriter::WriteDexFiles(File* file, if (copy_dex_files == CopyOption::kOnlyIfCompressed) { extract_dex_files_into_vdex_ = false; for (OatDexFile& oat_dex_file : oat_dex_files_) { - const DexFileContainer* container = oat_dex_file.GetDexFile()->GetContainer(); + const DexFileContainer* container = oat_dex_file.GetDexFile()->GetContainer().get(); if (!(container->IsZip() && container->IsFileMap())) { extract_dex_files_into_vdex_ = true; break; @@ -3398,6 +3398,7 @@ bool OatWriter::OpenDexFiles( DCHECK_EQ(opened_dex_files_map->size(), 1u); DCHECK(vdex_begin_ == opened_dex_files_map->front().Begin()); std::vector<std::unique_ptr<const DexFile>> dex_files; + auto dex_container = std::make_shared<MemoryDexFileContainer>(vdex_begin_, vdex_size_); for (OatDexFile& oat_dex_file : oat_dex_files_) { const uint8_t* raw_dex_file = vdex_begin_ + oat_dex_file.dex_file_offset_; @@ -3418,10 +3419,10 @@ bool OatWriter::OpenDexFiles( // Now, open the dex file. std::string error_msg; - ArtDexFileLoader dex_file_loader( - raw_dex_file, oat_dex_file.dex_file_size_, oat_dex_file.GetLocation()); + ArtDexFileLoader dex_file_loader(dex_container, oat_dex_file.GetLocation()); // All dex files have been already verified in WriteDexFiles before we copied them. - dex_files.emplace_back(dex_file_loader.Open(oat_dex_file.dex_file_location_checksum_, + dex_files.emplace_back(dex_file_loader.Open(oat_dex_file.dex_file_offset_, + oat_dex_file.dex_file_location_checksum_, /*oat_dex_file=*/nullptr, /*verify=*/false, /*verify_checksum=*/false, diff --git a/libartbase/base/mem_map.cc b/libartbase/base/mem_map.cc index 4c14af132c..5c88b7ee14 100644 --- a/libartbase/base/mem_map.cc +++ b/libartbase/base/mem_map.cc @@ -655,9 +655,12 @@ void MemMap::Invalidate() { DCHECK(IsValid()); // Remove it from gMaps. - std::lock_guard<std::mutex> mu(*mem_maps_lock_); - auto it = GetGMapsEntry(*this); - gMaps->erase(it); + // TODO(b/307704260) Move MemMap::Init MemMap::Shutdown out of Runtime init/shutdown. + if (mem_maps_lock_ != nullptr) { // Runtime was shutdown. + std::lock_guard<std::mutex> mu(*mem_maps_lock_); + auto it = GetGMapsEntry(*this); + gMaps->erase(it); + } // Mark it as invalid. base_size_ = 0u; diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h index bda5bce2fc..30516752b3 100644 --- a/libdexfile/dex/dex_file.h +++ b/libdexfile/dex/dex_file.h @@ -57,8 +57,9 @@ enum class Domain : char; // Owns the physical storage that backs one or more DexFiles (that is, it can be shared). // It frees the storage (e.g. closes file) when all DexFiles that use it are all closed. // -// The Begin()-End() range represents exactly one DexFile (with the size from the header). -// In particular, the End() does NOT include any shared cdex data from other DexFiles. +// The memory range must include all data used by the DexFiles including any shared data. +// +// It might also include surrounding non-dex data (e.g. it might represent vdex file). class DexFileContainer { public: DexFileContainer() { } @@ -845,9 +846,7 @@ class DexFile { return DataBegin() <= addr && addr < DataBegin() + DataSize(); } - DexFileContainer* GetContainer() const { - return container_.get(); - } + const std::shared_ptr<DexFileContainer>& GetContainer() const { return container_; } IterationRange<ClassIterator> GetClasses() const; diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc index 996204f365..0fc99357e3 100644 --- a/libdexfile/dex/dex_file_loader.cc +++ b/libdexfile/dex/dex_file_loader.cc @@ -164,7 +164,7 @@ bool DexFileLoader::GetMultiDexChecksum(std::optional<uint32_t>* checksum, checksum->reset(); // Return nullopt for an empty zip archive. uint32_t magic; - if (!InitAndReadMagic(&magic, error_msg)) { + if (!InitAndReadMagic(/*header_offset=*/0, &magic, error_msg)) { return false; } @@ -252,7 +252,8 @@ DexFileLoader::DexFileLoader(std::vector<uint8_t>&& memory, const std::string& l DexFileLoader::DexFileLoader(MemMap&& mem_map, const std::string& location) : DexFileLoader(std::make_shared<MemMapContainer>(std::move(mem_map)), location) {} -std::unique_ptr<const DexFile> DexFileLoader::Open(uint32_t location_checksum, +std::unique_ptr<const DexFile> DexFileLoader::Open(size_t header_offset, + uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, bool verify_checksum, @@ -260,14 +261,15 @@ std::unique_ptr<const DexFile> DexFileLoader::Open(uint32_t location_checksum, DEXFILE_SCOPED_TRACE(std::string("Open dex file ") + location_); uint32_t magic; - if (!InitAndReadMagic(&magic, error_msg) || !MapRootContainer(error_msg)) { + if (!InitAndReadMagic(header_offset, &magic, error_msg) || !MapRootContainer(error_msg)) { DCHECK(!error_msg->empty()); return {}; } DCHECK(root_container_ != nullptr); + DCHECK_LE(header_offset, root_container_->Size()); std::unique_ptr<const DexFile> dex_file = OpenCommon(root_container_, - root_container_->Begin(), - root_container_->Size(), + root_container_->Begin() + header_offset, + root_container_->Size() - header_offset, location_, location_checksum, oat_dex_file, @@ -278,13 +280,16 @@ std::unique_ptr<const DexFile> DexFileLoader::Open(uint32_t location_checksum, return dex_file; } -bool DexFileLoader::InitAndReadMagic(uint32_t* magic, std::string* error_msg) { +bool DexFileLoader::InitAndReadMagic(size_t header_offset, + uint32_t* magic, + std::string* error_msg) { if (root_container_ != nullptr) { - if (root_container_->Size() < sizeof(uint32_t)) { + if (root_container_->Size() < header_offset || + root_container_->Size() - header_offset < sizeof(uint32_t)) { *error_msg = StringPrintf("Unable to open '%s' : Size is too small", location_.c_str()); return false; } - *magic = *reinterpret_cast<const uint32_t*>(root_container_->Begin()); + *magic = *reinterpret_cast<const uint32_t*>(root_container_->Begin() + header_offset); } else { // Open the file if we have not been given the file-descriptor directly before. if (!file_->IsValid()) { @@ -296,6 +301,7 @@ bool DexFileLoader::InitAndReadMagic(uint32_t* magic, std::string* error_msg) { } file_ = &owned_file_.value(); } + CHECK_EQ(header_offset, 0u); // We always expect to read from the start of physical file. if (!ReadMagicAndReset(file_->Fd(), magic, error_msg)) { return false; } @@ -347,7 +353,7 @@ bool DexFileLoader::Open(bool verify, DCHECK(dex_files != nullptr) << "DexFile::Open: out-param is nullptr"; uint32_t magic; - if (!InitAndReadMagic(&magic, error_msg)) { + if (!InitAndReadMagic(/*header_offset=*/0, &magic, error_msg)) { return false; } @@ -416,7 +422,7 @@ bool DexFileLoader::Open(bool verify, std::unique_ptr<DexFile> DexFileLoader::OpenCommon(std::shared_ptr<DexFileContainer> container, const uint8_t* base, - size_t size, + size_t app_compat_size, const std::string& location, std::optional<uint32_t> location_checksum, const OatDexFile* oat_dex_file, @@ -426,8 +432,11 @@ std::unique_ptr<DexFile> DexFileLoader::OpenCommon(std::shared_ptr<DexFileContai DexFileLoaderErrorCode* error_code) { if (container == nullptr) { // We should never pass null here, but use reasonable default for app compat anyway. - container = std::make_shared<MemoryDexFileContainer>(base, size); + container = std::make_shared<MemoryDexFileContainer>(base, app_compat_size); } + CHECK_GE(base, container->Begin()); + CHECK_LE(base, container->End()); + const size_t size = container->End() - base; if (error_code != nullptr) { *error_code = DexFileLoaderErrorCode::kDexFileError; } diff --git a/libdexfile/dex/dex_file_loader.h b/libdexfile/dex/dex_file_loader.h index ec5f64a9d6..be3359b98f 100644 --- a/libdexfile/dex/dex_file_loader.h +++ b/libdexfile/dex/dex_file_loader.h @@ -180,17 +180,28 @@ class DexFileLoader { virtual ~DexFileLoader() {} - std::unique_ptr<const DexFile> Open(uint32_t location_checksum, + std::unique_ptr<const DexFile> Open(size_t header_offset, + uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, bool verify_checksum, std::string* error_msg); std::unique_ptr<const DexFile> Open(uint32_t location_checksum, + const OatDexFile* oat_dex_file, + bool verify, + bool verify_checksum, + std::string* error_msg) { + return Open( + /*header_offset=*/0, location_checksum, oat_dex_file, verify, verify_checksum, error_msg); + } + + std::unique_ptr<const DexFile> Open(uint32_t location_checksum, bool verify, bool verify_checksum, std::string* error_msg) { - return Open(location_checksum, + return Open(/*header_offset=*/0, + location_checksum, /*oat_dex_file=*/nullptr, verify, verify_checksum, @@ -243,7 +254,7 @@ class DexFileLoader { protected: static const File kInvalidFile; // Used for "no file descriptor" (-1). - bool InitAndReadMagic(uint32_t* magic, std::string* error_msg); + bool InitAndReadMagic(size_t header_offset, uint32_t* magic, std::string* error_msg); // Ensure we have root container. If we are backed by a file, memory-map it. // We can only do this for dex files since zip files might be too big to map. diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 3b1980b4f3..a518b3416c 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -548,6 +548,7 @@ bool OatFileBase::Setup(const std::vector<const DexFile*>& dex_files, std::strin } // Create an OatDexFile and add it to the owning container. OatDexFile* oat_dex_file = new OatDexFile(this, + dex_file->GetContainer(), dex_file->Begin(), dex_file->GetHeader().magic_, dex_file->GetLocationChecksum(), @@ -794,6 +795,7 @@ bool OatFileBase::Setup(int zip_fd, DexSize()); return false; } + std::shared_ptr<DexFileContainer> dex_file_container; const uint8_t* dex_file_pointer = nullptr; if (UNLIKELY(dex_file_offset == 0U)) { // Do not support mixed-mode oat files. @@ -814,23 +816,17 @@ bool OatFileBase::Setup(int zip_fd, if (zip_fd != -1) { File file(zip_fd, /*check_usage=*/false); ArtDexFileLoader dex_file_loader(&file, dex_file_location); - loaded = dex_file_loader.Open(/*verify=*/false, - /*verify_checksum=*/false, - error_msg, - &new_dex_files); + loaded = dex_file_loader.Open( + /*verify=*/false, /*verify_checksum=*/false, error_msg, &new_dex_files); } else if (dex_file->IsValid()) { // Note that we assume dex_fds are backing by jars. ArtDexFileLoader dex_file_loader(dex_file, dex_file_location); - loaded = dex_file_loader.Open(/*verify=*/false, - /*verify_checksum=*/false, - error_msg, - &new_dex_files); + loaded = dex_file_loader.Open( + /*verify=*/false, /*verify_checksum=*/false, error_msg, &new_dex_files); } else { ArtDexFileLoader dex_file_loader(dex_file_name.c_str(), dex_file_location); - loaded = dex_file_loader.Open(/*verify=*/false, - /*verify_checksum=*/false, - error_msg, - &new_dex_files); + loaded = dex_file_loader.Open( + /*verify=*/false, /*verify_checksum=*/false, error_msg, &new_dex_files); } if (!loaded) { if (Runtime::Current() == nullptr) { @@ -880,6 +876,7 @@ bool OatFileBase::Setup(int zip_fd, return false; } CHECK(dex_file_sha1 == external_dex_files_[i]->GetSha1()); + dex_file_container = external_dex_files_[i]->GetContainer(); dex_file_pointer = external_dex_files_[i]->Begin(); } else { // Do not support mixed-mode oat files. @@ -902,6 +899,7 @@ bool OatFileBase::Setup(int zip_fd, sizeof(DexFile::Header)); return false; } + dex_file_container = std::make_shared<MemoryDexFileContainer>(DexBegin(), DexEnd()); dex_file_pointer = DexBegin() + dex_file_offset; } @@ -1032,6 +1030,7 @@ bool OatFileBase::Setup(int zip_fd, dex_file_magic, dex_file_checksum, dex_file_sha1, + dex_file_container, dex_file_pointer, lookup_table_data, method_bss_mapping, @@ -1761,6 +1760,8 @@ class OatFileBackedByVdex final : public OatFileBase { if (vdex_file->HasDexSection()) { uint32_t i = 0; const uint8_t* type_lookup_table_start = nullptr; + auto dex_file_container = + std::make_shared<MemoryDexFileContainer>(vdex_file->Begin(), vdex_file->End()); for (const uint8_t* dex_file_start = vdex_file->GetNextDexFileData(nullptr, i); dex_file_start != nullptr; dex_file_start = vdex_file->GetNextDexFileData(dex_file_start, ++i)) { @@ -1807,6 +1808,7 @@ class OatFileBackedByVdex final : public OatFileBase { } OatDexFile* oat_dex_file = new OatDexFile(oat_file.get(), + dex_file_container, dex_file_start, header->magic_, vdex_file->GetLocationChecksum(i), @@ -2174,6 +2176,7 @@ OatDexFile::OatDexFile(const OatFile* oat_file, DexFile::Magic dex_file_magic, uint32_t dex_file_location_checksum, DexFile::Sha1 dex_file_sha1, + const std::shared_ptr<DexFileContainer>& dex_file_container, const uint8_t* dex_file_pointer, const uint8_t* lookup_table_data, const IndexBssMapping* method_bss_mapping_data, @@ -2189,6 +2192,7 @@ OatDexFile::OatDexFile(const OatFile* oat_file, dex_file_magic_(dex_file_magic), dex_file_location_checksum_(dex_file_location_checksum), dex_file_sha1_(dex_file_sha1), + dex_file_container_(dex_file_container), dex_file_pointer_(dex_file_pointer), lookup_table_data_(lookup_table_data), method_bss_mapping_(method_bss_mapping_data), @@ -2224,6 +2228,7 @@ void OatDexFile::InitializeTypeLookupTable() { } OatDexFile::OatDexFile(const OatFile* oat_file, + const std::shared_ptr<DexFileContainer>& dex_file_container, const uint8_t* dex_file_pointer, DexFile::Magic dex_file_magic, uint32_t dex_file_location_checksum, @@ -2237,6 +2242,7 @@ OatDexFile::OatDexFile(const OatFile* oat_file, dex_file_magic_(dex_file_magic), dex_file_location_checksum_(dex_file_location_checksum), dex_file_sha1_(dex_file_sha1), + dex_file_container_(dex_file_container), dex_file_pointer_(dex_file_pointer), lookup_table_data_(lookup_table_data) { InitializeTypeLookupTable(); @@ -2262,9 +2268,13 @@ std::unique_ptr<const DexFile> OatDexFile::OpenDexFile(std::string* error_msg) c ScopedTrace trace(__PRETTY_FUNCTION__); static constexpr bool kVerify = false; static constexpr bool kVerifyChecksum = false; - ArtDexFileLoader dex_file_loader(dex_file_pointer_, FileSize(), dex_file_location_); - return dex_file_loader.Open( - dex_file_location_checksum_, this, kVerify, kVerifyChecksum, error_msg); + ArtDexFileLoader dex_file_loader(dex_file_container_, dex_file_location_); + return dex_file_loader.Open(dex_file_pointer_ - dex_file_container_->Begin(), + dex_file_location_checksum_, + this, + kVerify, + kVerifyChecksum, + error_msg); } uint32_t OatDexFile::GetOatClassOffset(uint16_t class_def_index) const { diff --git a/runtime/oat_file.h b/runtime/oat_file.h index 13c7ba1424..806e616770 100644 --- a/runtime/oat_file.h +++ b/runtime/oat_file.h @@ -18,6 +18,7 @@ #define ART_RUNTIME_OAT_FILE_H_ #include <list> +#include <memory> #include <string> #include <string_view> #include <vector> @@ -598,6 +599,7 @@ class OatDexFile final { DexFile::Magic dex_file_magic, uint32_t dex_file_checksum, DexFile::Sha1 dex_file_sha1, + const std::shared_ptr<DexFileContainer>& dex_file_container_, const uint8_t* dex_file_pointer, const uint8_t* lookup_table_data, const IndexBssMapping* method_bss_mapping, @@ -611,6 +613,7 @@ class OatDexFile final { // Create an OatDexFile wrapping an existing DexFile. Will set the OatDexFile // pointer in the DexFile. OatDexFile(const OatFile* oat_file, + const std::shared_ptr<DexFileContainer>& dex_file_container_, const uint8_t* dex_file_pointer, DexFile::Magic dex_file_magic, uint32_t dex_file_checksum, @@ -630,6 +633,7 @@ class OatDexFile final { const DexFile::Magic dex_file_magic_ = {}; const uint32_t dex_file_location_checksum_ = 0u; const DexFile::Sha1 dex_file_sha1_ = {}; + const std::shared_ptr<DexFileContainer> dex_file_container_; const uint8_t* const dex_file_pointer_ = nullptr; const uint8_t* const lookup_table_data_ = nullptr; const IndexBssMapping* const method_bss_mapping_ = nullptr; diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc index ef4fb5e694..868e5e56bd 100644 --- a/runtime/vdex_file.cc +++ b/runtime/vdex_file.cc @@ -215,15 +215,16 @@ const uint8_t* VdexFile::GetNextTypeLookupTableData(const uint8_t* cursor, bool VdexFile::OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files, std::string* error_msg) const { size_t i = 0; + auto dex_file_container = std::make_shared<MemoryDexFileContainer>(Begin(), End()); for (const uint8_t* dex_file_start = GetNextDexFileData(nullptr, i); dex_file_start != nullptr; dex_file_start = GetNextDexFileData(dex_file_start, ++i)) { - size_t size = reinterpret_cast<const DexFile::Header*>(dex_file_start)->file_size_; // TODO: Supply the location information for a vdex file. static constexpr char kVdexLocation[] = ""; std::string location = DexFileLoader::GetMultiDexLocation(i, kVdexLocation); - ArtDexFileLoader dex_file_loader(dex_file_start, size, location); - std::unique_ptr<const DexFile> dex(dex_file_loader.Open(GetLocationChecksum(i), + ArtDexFileLoader dex_file_loader(dex_file_container, location); + std::unique_ptr<const DexFile> dex(dex_file_loader.Open(dex_file_start - Begin(), + GetLocationChecksum(i), /*oat_dex_file=*/nullptr, /*verify=*/false, /*verify_checksum=*/false, |