From 5ffefaa41de9b9e711f6e8bc7ed9ff9e9d844fe7 Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Fri, 25 Jan 2019 01:04:54 -0800 Subject: Ensure the correctness of fast verify We cannot guarantee that the resolution recorded in the vdex file is correct when the boot classes are redefined. For example we might be doing only sdk verification and not have the entire context available - as such, if an app redefines a class that is in the boot classpath but not the sdk we might record the wrong resolution. Another example is OTA time, when the boot classpath may change. The CL discards the vdex file when the app redefines classes from boot classpath. Test: test/testrunner/testrunner.py -t 719 Bug: 122968669 Change-Id: If0c56b1970d8ebe701d198ffccec52f586aea9e6 --- compiler/driver/compiler_driver.cc | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'compiler/driver/compiler_driver.cc') diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index e440eec735..d46cffb1e8 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -1765,6 +1765,42 @@ static void LoadAndUpdateStatus(const ClassAccessor& accessor, } } +// Returns true if any of the given dex files define a class from the boot classpath. +static bool DexFilesRedefineBootClasses( + const std::vector& dex_files, + TimingLogger* timings) { + TimingLogger::ScopedTiming t("Fast Verify: Boot Class Redefinition Check", timings); + + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Thread* self = Thread::Current(); + ScopedObjectAccess soa(self); + + bool foundRedefinition = false; + for (const DexFile* dex_file : dex_files) { + for (ClassAccessor accessor : dex_file->GetClasses()) { + const char* descriptor = accessor.GetDescriptor(); + StackHandleScope<1> hs_class(self); + Handle klass = + hs_class.NewHandle(class_linker->FindSystemClass(self, descriptor)); + if (klass == nullptr) { + self->ClearException(); + } else { + LOG(WARNING) << "Redefinition of boot class " << descriptor + << " App dex file: " << accessor.GetDexFile().GetLocation() + << " Boot dex file: " << klass->GetDexFile().GetLocation(); + foundRedefinition = true; + if (!VLOG_IS_ON(verifier)) { + // If we are not in verbose mode, return early. + // Otherwise continue and log all the collisions for easier debugging. + return true; + } + } + } + } + + return foundRedefinition; +} + bool CompilerDriver::FastVerify(jobject jclass_loader, const std::vector& dex_files, TimingLogger* timings, @@ -1776,6 +1812,17 @@ bool CompilerDriver::FastVerify(jobject jclass_loader, return false; } TimingLogger::ScopedTiming t("Fast Verify", timings); + + // We cannot do fast verification if the app redefines classes from the boot classpath. + // Vdex does not record resolution chains for boot classes and we might wrongfully + // resolve a class to the app when it should have been resolved to the boot classpath + // (e.g. if we verified against the SDK and the app redefines a boot class which is not + // in the SDK.) + if (DexFilesRedefineBootClasses(dex_files, timings)) { + LOG(WARNING) << "Found redefinition of boot classes. Not doing fast verification."; + return false; + } + ScopedObjectAccess soa(Thread::Current()); StackHandleScope<2> hs(soa.Self()); Handle class_loader( -- cgit v1.2.3-59-g8ed1b