1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "vdex_file.h"
18
19 #include <sys/mman.h> // For the PROT_* and MAP_* constants.
20 #include <sys/stat.h> // for mkdir()
21
22 #include <memory>
23 #include <unordered_set>
24
25 #include <android-base/logging.h>
26
27 #include "base/bit_utils.h"
28 #include "base/leb128.h"
29 #include "base/stl_util.h"
30 #include "base/systrace.h"
31 #include "base/unix_file/fd_file.h"
32 #include "class_linker.h"
33 #include "class_loader_context.h"
34 #include "dex/art_dex_file_loader.h"
35 #include "dex/class_accessor-inl.h"
36 #include "dex/dex_file_loader.h"
37 #include "gc/heap.h"
38 #include "gc/space/image_space.h"
39 #include "mirror/class-inl.h"
40 #include "quicken_info.h"
41 #include "handle_scope-inl.h"
42 #include "runtime.h"
43 #include "verifier/verifier_deps.h"
44
45 namespace art {
46
47 constexpr uint8_t VdexFile::VdexFileHeader::kVdexInvalidMagic[4];
48 constexpr uint8_t VdexFile::VdexFileHeader::kVdexMagic[4];
49 constexpr uint8_t VdexFile::VdexFileHeader::kVdexVersion[4];
50
IsMagicValid() const51 bool VdexFile::VdexFileHeader::IsMagicValid() const {
52 return (memcmp(magic_, kVdexMagic, sizeof(kVdexMagic)) == 0);
53 }
54
IsVdexVersionValid() const55 bool VdexFile::VdexFileHeader::IsVdexVersionValid() const {
56 return (memcmp(vdex_version_, kVdexVersion, sizeof(kVdexVersion)) == 0);
57 }
58
VdexFileHeader(bool has_dex_section ATTRIBUTE_UNUSED)59 VdexFile::VdexFileHeader::VdexFileHeader(bool has_dex_section ATTRIBUTE_UNUSED)
60 : number_of_sections_(static_cast<uint32_t>(VdexSection::kNumberOfSections)) {
61 memcpy(magic_, kVdexMagic, sizeof(kVdexMagic));
62 memcpy(vdex_version_, kVdexVersion, sizeof(kVdexVersion));
63 DCHECK(IsMagicValid());
64 DCHECK(IsVdexVersionValid());
65 }
66
OpenAtAddress(uint8_t * mmap_addr,size_t mmap_size,bool mmap_reuse,const std::string & vdex_filename,bool writable,bool low_4gb,bool unquicken,std::string * error_msg)67 std::unique_ptr<VdexFile> VdexFile::OpenAtAddress(uint8_t* mmap_addr,
68 size_t mmap_size,
69 bool mmap_reuse,
70 const std::string& vdex_filename,
71 bool writable,
72 bool low_4gb,
73 bool unquicken,
74 std::string* error_msg) {
75 ScopedTrace trace(("VdexFile::OpenAtAddress " + vdex_filename).c_str());
76 if (!OS::FileExists(vdex_filename.c_str())) {
77 *error_msg = "File " + vdex_filename + " does not exist.";
78 return nullptr;
79 }
80
81 std::unique_ptr<File> vdex_file;
82 if (writable) {
83 vdex_file.reset(OS::OpenFileReadWrite(vdex_filename.c_str()));
84 } else {
85 vdex_file.reset(OS::OpenFileForReading(vdex_filename.c_str()));
86 }
87 if (vdex_file == nullptr) {
88 *error_msg = "Could not open file " + vdex_filename +
89 (writable ? " for read/write" : "for reading");
90 return nullptr;
91 }
92
93 int64_t vdex_length = vdex_file->GetLength();
94 if (vdex_length == -1) {
95 *error_msg = "Could not read the length of file " + vdex_filename;
96 return nullptr;
97 }
98
99 return OpenAtAddress(mmap_addr,
100 mmap_size,
101 mmap_reuse,
102 vdex_file->Fd(),
103 vdex_length,
104 vdex_filename,
105 writable,
106 low_4gb,
107 unquicken,
108 error_msg);
109 }
110
OpenAtAddress(uint8_t * mmap_addr,size_t mmap_size,bool mmap_reuse,int file_fd,size_t vdex_length,const std::string & vdex_filename,bool writable,bool low_4gb,bool unquicken,std::string * error_msg)111 std::unique_ptr<VdexFile> VdexFile::OpenAtAddress(uint8_t* mmap_addr,
112 size_t mmap_size,
113 bool mmap_reuse,
114 int file_fd,
115 size_t vdex_length,
116 const std::string& vdex_filename,
117 bool writable,
118 bool low_4gb,
119 bool unquicken,
120 std::string* error_msg) {
121 if (mmap_addr != nullptr && mmap_size < vdex_length) {
122 LOG(WARNING) << "Insufficient pre-allocated space to mmap vdex.";
123 mmap_addr = nullptr;
124 mmap_reuse = false;
125 }
126 CHECK(!mmap_reuse || mmap_addr != nullptr);
127 CHECK(!(writable && unquicken)) << "We don't want to be writing unquickened files out to disk!";
128 // Start as PROT_WRITE so we can mprotect back to it if we want to.
129 MemMap mmap = MemMap::MapFileAtAddress(
130 mmap_addr,
131 vdex_length,
132 PROT_READ | PROT_WRITE,
133 writable ? MAP_SHARED : MAP_PRIVATE,
134 file_fd,
135 /* start= */ 0u,
136 low_4gb,
137 vdex_filename.c_str(),
138 mmap_reuse,
139 /* reservation= */ nullptr,
140 error_msg);
141 if (!mmap.IsValid()) {
142 *error_msg = "Failed to mmap file " + vdex_filename + " : " + *error_msg;
143 return nullptr;
144 }
145
146 std::unique_ptr<VdexFile> vdex(new VdexFile(std::move(mmap)));
147 if (!vdex->IsValid()) {
148 *error_msg = "Vdex file is not valid";
149 return nullptr;
150 }
151
152 if (!writable) {
153 Runtime* runtime = Runtime::Current();
154 // The runtime might not be available at this point if we're running
155 // dex2oat or oatdump.
156 if (runtime != nullptr) {
157 size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeVdex();
158 Runtime::MadviseFileForRange(madvise_size_limit,
159 vdex->Size(),
160 vdex->Begin(),
161 vdex->End(),
162 vdex_filename);
163 }
164 }
165
166 return vdex;
167 }
168
GetNextDexFileData(const uint8_t * cursor,uint32_t dex_file_index) const169 const uint8_t* VdexFile::GetNextDexFileData(const uint8_t* cursor, uint32_t dex_file_index) const {
170 DCHECK(cursor == nullptr || (cursor > Begin() && cursor <= End()));
171 if (cursor == nullptr) {
172 // Beginning of the iteration, return the first dex file if there is one.
173 return HasDexSection() ? DexBegin() : nullptr;
174 } else if (dex_file_index >= GetNumberOfDexFiles()) {
175 return nullptr;
176 } else {
177 // Fetch the next dex file. Return null if there is none.
178 const uint8_t* data = cursor + reinterpret_cast<const DexFile::Header*>(cursor)->file_size_;
179 // Dex files are required to be 4 byte aligned. the OatWriter makes sure they are, see
180 // OatWriter::SeekToDexFiles.
181 return AlignUp(data, 4);
182 }
183 }
184
GetNextTypeLookupTableData(const uint8_t * cursor,uint32_t dex_file_index) const185 const uint8_t* VdexFile::GetNextTypeLookupTableData(const uint8_t* cursor,
186 uint32_t dex_file_index) const {
187 if (cursor == nullptr) {
188 // Beginning of the iteration, return the first dex file if there is one.
189 return HasTypeLookupTableSection() ? TypeLookupTableDataBegin() : nullptr;
190 } else if (dex_file_index >= GetNumberOfDexFiles()) {
191 return nullptr;
192 } else {
193 const uint8_t* data = cursor + sizeof(uint32_t) + reinterpret_cast<const uint32_t*>(cursor)[0];
194 // TypeLookupTables are required to be 4 byte aligned. the OatWriter makes sure they are.
195 CHECK_ALIGNED(data, 4);
196 return data;
197 }
198 }
199
OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>> * dex_files,std::string * error_msg) const200 bool VdexFile::OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
201 std::string* error_msg) const {
202 const ArtDexFileLoader dex_file_loader;
203 size_t i = 0;
204 for (const uint8_t* dex_file_start = GetNextDexFileData(nullptr, i);
205 dex_file_start != nullptr;
206 dex_file_start = GetNextDexFileData(dex_file_start, ++i)) {
207 size_t size = reinterpret_cast<const DexFile::Header*>(dex_file_start)->file_size_;
208 // TODO: Supply the location information for a vdex file.
209 static constexpr char kVdexLocation[] = "";
210 std::string location = DexFileLoader::GetMultiDexLocation(i, kVdexLocation);
211 std::unique_ptr<const DexFile> dex(dex_file_loader.OpenWithDataSection(
212 dex_file_start,
213 size,
214 /*data_base=*/ nullptr,
215 /*data_size=*/ 0u,
216 location,
217 GetLocationChecksum(i),
218 /*oat_dex_file=*/ nullptr,
219 /*verify=*/ false,
220 /*verify_checksum=*/ false,
221 error_msg));
222 if (dex == nullptr) {
223 return false;
224 }
225 dex_files->push_back(std::move(dex));
226 }
227 return true;
228 }
229
CreateDirectories(const std::string & child_path,std::string * error_msg)230 static bool CreateDirectories(const std::string& child_path, /* out */ std::string* error_msg) {
231 size_t last_slash_pos = child_path.find_last_of('/');
232 CHECK_NE(last_slash_pos, std::string::npos) << "Invalid path: " << child_path;
233 std::string parent_path = child_path.substr(0, last_slash_pos);
234 if (OS::DirectoryExists(parent_path.c_str())) {
235 return true;
236 } else if (CreateDirectories(parent_path, error_msg)) {
237 if (mkdir(parent_path.c_str(), 0700) == 0) {
238 return true;
239 }
240 *error_msg = "Could not create directory " + parent_path;
241 return false;
242 } else {
243 return false;
244 }
245 }
246
WriteToDisk(const std::string & path,const std::vector<const DexFile * > & dex_files,const verifier::VerifierDeps & verifier_deps,std::string * error_msg)247 bool VdexFile::WriteToDisk(const std::string& path,
248 const std::vector<const DexFile*>& dex_files,
249 const verifier::VerifierDeps& verifier_deps,
250 std::string* error_msg) {
251 std::vector<uint8_t> verifier_deps_data;
252 verifier_deps.Encode(dex_files, &verifier_deps_data);
253 uint32_t verifier_deps_size = verifier_deps_data.size();
254 // Add padding so the type lookup tables are 4 byte aligned.
255 uint32_t verifier_deps_with_padding_size = RoundUp(verifier_deps_data.size(), 4);
256 DCHECK_GE(verifier_deps_with_padding_size, verifier_deps_data.size());
257 verifier_deps_data.resize(verifier_deps_with_padding_size, 0);
258
259 size_t type_lookup_table_size = 0u;
260 for (const DexFile* dex_file : dex_files) {
261 type_lookup_table_size +=
262 sizeof(uint32_t) + TypeLookupTable::RawDataLength(dex_file->NumClassDefs());
263 }
264
265 VdexFile::VdexFileHeader vdex_header(/* has_dex_section= */ false);
266 VdexFile::VdexSectionHeader sections[static_cast<uint32_t>(VdexSection::kNumberOfSections)];
267
268 // Set checksum section.
269 sections[VdexSection::kChecksumSection].section_kind = VdexSection::kChecksumSection;
270 sections[VdexSection::kChecksumSection].section_offset = GetChecksumsOffset();
271 sections[VdexSection::kChecksumSection].section_size =
272 sizeof(VdexFile::VdexChecksum) * dex_files.size();
273
274 // Set dex section.
275 sections[VdexSection::kDexFileSection].section_kind = VdexSection::kDexFileSection;
276 sections[VdexSection::kDexFileSection].section_offset = 0u;
277 sections[VdexSection::kDexFileSection].section_size = 0u;
278
279 // Set VerifierDeps section.
280 sections[VdexSection::kVerifierDepsSection].section_kind = VdexSection::kVerifierDepsSection;
281 sections[VdexSection::kVerifierDepsSection].section_offset =
282 GetChecksumsOffset() + sections[kChecksumSection].section_size;
283 sections[VdexSection::kVerifierDepsSection].section_size = verifier_deps_size;
284
285 // Set TypeLookupTable section.
286 sections[VdexSection::kTypeLookupTableSection].section_kind =
287 VdexSection::kTypeLookupTableSection;
288 sections[VdexSection::kTypeLookupTableSection].section_offset =
289 sections[VdexSection::kVerifierDepsSection].section_offset + verifier_deps_with_padding_size;
290 sections[VdexSection::kTypeLookupTableSection].section_size = type_lookup_table_size;
291
292 if (!CreateDirectories(path, error_msg)) {
293 return false;
294 }
295
296 std::unique_ptr<File> out(OS::CreateEmptyFileWriteOnly(path.c_str()));
297 if (out == nullptr) {
298 *error_msg = "Could not open " + path + " for writing";
299 return false;
300 }
301
302 // Write header.
303 if (!out->WriteFully(reinterpret_cast<const char*>(&vdex_header), sizeof(vdex_header))) {
304 *error_msg = "Could not write vdex header to " + path;
305 out->Unlink();
306 return false;
307 }
308
309 // Write section infos.
310 if (!out->WriteFully(reinterpret_cast<const char*>(§ions), sizeof(sections))) {
311 *error_msg = "Could not write vdex sections to " + path;
312 out->Unlink();
313 return false;
314 }
315
316 // Write checksum section.
317 for (const DexFile* dex_file : dex_files) {
318 uint32_t checksum = dex_file->GetLocationChecksum();
319 const uint32_t* checksum_ptr = &checksum;
320 static_assert(sizeof(*checksum_ptr) == sizeof(VdexFile::VdexChecksum));
321 if (!out->WriteFully(reinterpret_cast<const char*>(checksum_ptr),
322 sizeof(VdexFile::VdexChecksum))) {
323 *error_msg = "Could not write dex checksums to " + path;
324 out->Unlink();
325 return false;
326 }
327 }
328
329 if (!out->WriteFully(reinterpret_cast<const char*>(verifier_deps_data.data()),
330 verifier_deps_with_padding_size)) {
331 *error_msg = "Could not write verifier deps to " + path;
332 out->Unlink();
333 return false;
334 }
335
336 size_t written_type_lookup_table_size = 0;
337 for (const DexFile* dex_file : dex_files) {
338 TypeLookupTable type_lookup_table = TypeLookupTable::Create(*dex_file);
339 uint32_t size = type_lookup_table.RawDataLength();
340 DCHECK_ALIGNED(size, 4);
341 if (!out->WriteFully(reinterpret_cast<const char*>(&size), sizeof(uint32_t)) ||
342 !out->WriteFully(reinterpret_cast<const char*>(type_lookup_table.RawData()), size)) {
343 *error_msg = "Could not write type lookup table " + path;
344 out->Unlink();
345 return false;
346 }
347 written_type_lookup_table_size += sizeof(uint32_t) + size;
348 }
349 DCHECK_EQ(written_type_lookup_table_size, type_lookup_table_size);
350
351 if (out->FlushClose() != 0) {
352 *error_msg = "Could not flush and close " + path;
353 out->Unlink();
354 return false;
355 }
356
357 return true;
358 }
359
MatchesDexFileChecksums(const std::vector<const DexFile::Header * > & dex_headers) const360 bool VdexFile::MatchesDexFileChecksums(const std::vector<const DexFile::Header*>& dex_headers)
361 const {
362 if (dex_headers.size() != GetNumberOfDexFiles()) {
363 LOG(WARNING) << "Mismatch of number of dex files in vdex (expected="
364 << GetNumberOfDexFiles() << ", actual=" << dex_headers.size() << ")";
365 return false;
366 }
367 const VdexChecksum* checksums = GetDexChecksumsArray();
368 for (size_t i = 0; i < dex_headers.size(); ++i) {
369 if (checksums[i] != dex_headers[i]->checksum_) {
370 LOG(WARNING) << "Mismatch of dex file checksum in vdex (index=" << i << ")";
371 return false;
372 }
373 }
374 return true;
375 }
376
FindClassAndClearException(ClassLinker * class_linker,Thread * self,const char * name,Handle<mirror::ClassLoader> class_loader)377 static ObjPtr<mirror::Class> FindClassAndClearException(ClassLinker* class_linker,
378 Thread* self,
379 const char* name,
380 Handle<mirror::ClassLoader> class_loader)
381 REQUIRES_SHARED(Locks::mutator_lock_) {
382 ObjPtr<mirror::Class> result = class_linker->FindClass(self, name, class_loader);
383 if (result == nullptr) {
384 DCHECK(self->IsExceptionPending());
385 self->ClearException();
386 }
387 return result;
388 }
389
GetStringFromId(const DexFile & dex_file,dex::StringIndex string_id,uint32_t number_of_extra_strings,const uint32_t * extra_strings_offsets,const uint8_t * verifier_deps)390 static const char* GetStringFromId(const DexFile& dex_file,
391 dex::StringIndex string_id,
392 uint32_t number_of_extra_strings,
393 const uint32_t* extra_strings_offsets,
394 const uint8_t* verifier_deps) {
395 uint32_t num_ids_in_dex = dex_file.NumStringIds();
396 if (string_id.index_ < num_ids_in_dex) {
397 return dex_file.StringDataByIdx(string_id);
398 } else {
399 CHECK_LT(string_id.index_ - num_ids_in_dex, number_of_extra_strings);
400 uint32_t offset = extra_strings_offsets[string_id.index_ - num_ids_in_dex];
401 return reinterpret_cast<const char*>(verifier_deps) + offset;
402 }
403 }
404
405 // Returns an array of offsets where the assignability checks for each class
406 // definition are stored.
GetDexFileClassDefs(const uint8_t * verifier_deps,uint32_t index)407 static const uint32_t* GetDexFileClassDefs(const uint8_t* verifier_deps, uint32_t index) {
408 uint32_t dex_file_offset = reinterpret_cast<const uint32_t*>(verifier_deps)[index];
409 return reinterpret_cast<const uint32_t*>(verifier_deps + dex_file_offset);
410 }
411
412 // Returns an array of offsets where extra strings are stored.
GetExtraStringsOffsets(const DexFile & dex_file,const uint8_t * verifier_deps,const uint32_t * dex_file_class_defs,uint32_t * number_of_extra_strings)413 static const uint32_t* GetExtraStringsOffsets(const DexFile& dex_file,
414 const uint8_t* verifier_deps,
415 const uint32_t* dex_file_class_defs,
416 /*out*/ uint32_t* number_of_extra_strings) {
417 // The information for strings is right after dex_file_class_defs, 4-byte
418 // aligned
419 uint32_t end_of_assignability_types = dex_file_class_defs[dex_file.NumClassDefs()];
420 const uint8_t* strings_data_start =
421 AlignUp(verifier_deps + end_of_assignability_types, sizeof(uint32_t));
422 // First entry is the number of extra strings for this dex file.
423 *number_of_extra_strings = *reinterpret_cast<const uint32_t*>(strings_data_start);
424 // Then an array of offsets in `verifier_deps` for the extra strings.
425 return reinterpret_cast<const uint32_t*>(strings_data_start + sizeof(uint32_t));
426 }
427
ComputeClassStatus(Thread * self,Handle<mirror::Class> cls) const428 ClassStatus VdexFile::ComputeClassStatus(Thread* self, Handle<mirror::Class> cls) const {
429 const DexFile& dex_file = cls->GetDexFile();
430 uint16_t class_def_index = cls->GetDexClassDefIndex();
431
432 // Find which dex file index from within the vdex file.
433 uint32_t index = 0;
434 for (; index < GetNumberOfDexFiles(); ++index) {
435 if (dex_file.GetLocationChecksum() == GetLocationChecksum(index)) {
436 break;
437 }
438 }
439
440 DCHECK_NE(index, GetNumberOfDexFiles());
441
442 const uint8_t* verifier_deps = GetVerifierDepsData().data();
443 const uint32_t* dex_file_class_defs = GetDexFileClassDefs(verifier_deps, index);
444
445 // Fetch type checks offsets.
446 uint32_t class_def_offset = dex_file_class_defs[class_def_index];
447 if (class_def_offset == verifier::VerifierDeps::kNotVerifiedMarker) {
448 // Return a status that needs re-verification.
449 return ClassStatus::kResolved;
450 }
451 // End offset for this class's type checks. We know there is one and the loop
452 // will terminate.
453 uint32_t end_offset = verifier::VerifierDeps::kNotVerifiedMarker;
454 for (uint32_t i = class_def_index + 1; i < dex_file.NumClassDefs() + 1; ++i) {
455 end_offset = dex_file_class_defs[i];
456 if (end_offset != verifier::VerifierDeps::kNotVerifiedMarker) {
457 break;
458 }
459 }
460 DCHECK_NE(end_offset, verifier::VerifierDeps::kNotVerifiedMarker);
461
462 uint32_t number_of_extra_strings = 0;
463 // Offset where extra strings are stored.
464 const uint32_t* extra_strings_offsets = GetExtraStringsOffsets(dex_file,
465 verifier_deps,
466 dex_file_class_defs,
467 &number_of_extra_strings);
468
469 // Loop over and perform each assignability check.
470 StackHandleScope<3> hs(self);
471 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
472 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(cls->GetClassLoader()));
473 MutableHandle<mirror::Class> source(hs.NewHandle<mirror::Class>(nullptr));
474 MutableHandle<mirror::Class> destination(hs.NewHandle<mirror::Class>(nullptr));
475
476 const uint8_t* cursor = verifier_deps + class_def_offset;
477 const uint8_t* end = verifier_deps + end_offset;
478 while (cursor < end) {
479 uint32_t destination_index;
480 uint32_t source_index;
481 if (UNLIKELY(!DecodeUnsignedLeb128Checked(&cursor, end, &destination_index) ||
482 !DecodeUnsignedLeb128Checked(&cursor, end, &source_index))) {
483 // Error parsing the data, just return that we are not verified.
484 return ClassStatus::kResolved;
485 }
486 const char* destination_desc = GetStringFromId(dex_file,
487 dex::StringIndex(destination_index),
488 number_of_extra_strings,
489 extra_strings_offsets,
490 verifier_deps);
491 destination.Assign(
492 FindClassAndClearException(class_linker, self, destination_desc, class_loader));
493
494 const char* source_desc = GetStringFromId(dex_file,
495 dex::StringIndex(source_index),
496 number_of_extra_strings,
497 extra_strings_offsets,
498 verifier_deps);
499 source.Assign(FindClassAndClearException(class_linker, self, source_desc, class_loader));
500
501 if (destination == nullptr || source == nullptr) {
502 // The interpreter / compiler can handle a missing class.
503 continue;
504 }
505
506 DCHECK(destination->IsResolved() && source->IsResolved());
507 if (!destination->IsAssignableFrom(source.Get())) {
508 // An implicit assignability check is failing in the code, return that the
509 // class is not verified.
510 return ClassStatus::kResolved;
511 }
512 }
513
514 return ClassStatus::kVerifiedNeedsAccessChecks;
515 }
516
517 } // namespace art
518