summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author David Srbecky <dsrbecky@google.com> 2023-10-11 12:56:19 +0100
committer David Srbecky <dsrbecky@google.com> 2023-10-25 14:17:55 +0000
commit876085b17f2bc5efe6b64eee4ddc1be4e967a4f1 (patch)
tree68c201c1990d300cba2324988c43ce7cfa80f4d4
parentc13ae9cfc8883372637fb43d2c16b527cd2a5d2a (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.cc9
-rw-r--r--libartbase/base/mem_map.cc9
-rw-r--r--libdexfile/dex/dex_file.h9
-rw-r--r--libdexfile/dex/dex_file_loader.cc31
-rw-r--r--libdexfile/dex/dex_file_loader.h17
-rw-r--r--runtime/oat_file.cc40
-rw-r--r--runtime/oat_file.h4
-rw-r--r--runtime/vdex_file.cc7
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,