Revert "Revert "Integrate ClassLoaderContext check in OatFileAssistant::GetBestOatFile.""
This reverts commit 656fdcd7f2aa9920ecd464dbb59d284e17969baa.
Bug: 176960283
Reason for revert: Racy code fixed in https://android-review.googlesource.com/c/platform/art/+/1678727
Change-Id: I7561aa8fad060bd076006dd4b1fbffc076834635
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 245ae36..0bccc82 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -21,6 +21,7 @@
#include <sys/stat.h>
#include "zlib.h"
+#include "android-base/file.h"
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
@@ -67,8 +68,9 @@
case OatFileAssistant::kOatUpToDate:
stream << "kOatUpToDate";
break;
- default:
- UNREACHABLE();
+ case OatFileAssistant::kOatContextOutOfDate:
+ stream << "kOaContextOutOfDate";
+ break;
}
return stream;
@@ -76,10 +78,12 @@
OatFileAssistant::OatFileAssistant(const char* dex_location,
const InstructionSet isa,
+ ClassLoaderContext* context,
bool load_executable,
bool only_load_system_executable)
: OatFileAssistant(dex_location,
isa,
+ context,
load_executable,
only_load_system_executable,
/*vdex_fd=*/ -1,
@@ -89,12 +93,14 @@
OatFileAssistant::OatFileAssistant(const char* dex_location,
const InstructionSet isa,
+ ClassLoaderContext* context,
bool load_executable,
bool only_load_system_executable,
int vdex_fd,
int oat_fd,
int zip_fd)
- : isa_(isa),
+ : context_(context),
+ isa_(isa),
load_executable_(load_executable),
only_load_system_executable_(only_load_system_executable),
odex_(this, /*is_oat_location=*/ false),
@@ -103,6 +109,7 @@
vdex_for_oat_(this, /*is_oat_location=*/ true),
zip_fd_(zip_fd) {
CHECK(dex_location != nullptr) << "OatFileAssistant: null dex location";
+ CHECK(!load_executable || context != nullptr) << "Loading executable without a context";
if (zip_fd < 0) {
CHECK_LE(oat_fd, 0) << "zip_fd must be provided with valid oat_fd. zip_fd=" << zip_fd
@@ -192,14 +199,10 @@
}
int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target,
- ClassLoaderContext* class_loader_context,
- const std::vector<int>& context_fds,
bool profile_changed,
bool downgrade) {
OatFileInfo& info = GetBestInfo();
DexOptNeeded dexopt_needed = info.GetDexOptNeeded(target,
- class_loader_context,
- context_fds,
profile_changed,
downgrade);
if (info.IsOatLocation() || dexopt_needed == kDex2OatFromScratch) {
@@ -443,6 +446,10 @@
return kOatDexOutOfDate;
}
+ if (!ClassLoaderContextIsOkay(file)) {
+ return kOatContextOutOfDate;
+ }
+
return kOatUpToDate;
}
@@ -727,6 +734,7 @@
switch (Status()) {
case kOatCannotOpen:
case kOatDexOutOfDate:
+ case kOatContextOutOfDate:
case kOatBootImageOutOfDate: return false;
case kOatUpToDate: return true;
@@ -752,29 +760,17 @@
OatFileAssistant::DexOptNeeded OatFileAssistant::OatFileInfo::GetDexOptNeeded(
CompilerFilter::Filter target,
- ClassLoaderContext* context,
- const std::vector<int>& context_fds,
bool profile_changed,
bool downgrade) {
- bool filter_okay = CompilerFilterIsOkay(target, profile_changed, downgrade);
- bool class_loader_context_okay = ClassLoaderContextIsOkay(context, context_fds);
+ if (IsUseable()) {
+ return CompilerFilterIsOkay(target, profile_changed, downgrade)
+ ? kNoDexOptNeeded
+ : kDex2OatForFilter;
+ }
- // Only check the filter and relocation if the class loader context is ok.
- // If it is not, we will return kDex2OatFromScratch as the compilation needs to be redone.
- if (class_loader_context_okay) {
- if (filter_okay && Status() == kOatUpToDate) {
- // The oat file is in good shape as is.
- return kNoDexOptNeeded;
- }
-
- if (IsUseable()) {
- return kDex2OatForFilter;
- }
-
- if (Status() == kOatBootImageOutOfDate) {
- return kDex2OatForBootImage;
- }
+ if (Status() == kOatBootImageOutOfDate) {
+ return kDex2OatForBootImage;
}
if (oat_file_assistant_->HasDexFiles()) {
@@ -887,51 +883,36 @@
CompilerFilter::IsAsGoodAs(current, target);
}
-bool OatFileAssistant::OatFileInfo::ClassLoaderContextIsOkay(ClassLoaderContext* context,
- const std::vector<int>& context_fds) {
- const OatFile* file = GetFile();
- if (file == nullptr) {
- // No oat file means we have nothing to verify.
- return true;
- }
-
- if (file->IsBackedByVdexOnly()) {
+bool OatFileAssistant::ClassLoaderContextIsOkay(const OatFile& oat_file) const {
+ if (oat_file.IsBackedByVdexOnly()) {
// Only a vdex file, we don't depend on the class loader context.
return true;
}
- if (!CompilerFilter::IsVerificationEnabled(file->GetCompilerFilter())) {
+ if (!CompilerFilter::IsVerificationEnabled(oat_file.GetCompilerFilter())) {
// If verification is not enabled we don't need to verify the class loader context and we
// assume it's ok.
return true;
}
-
- if (context == nullptr) {
- // TODO(calin): stop using null for the unkown contexts.
- // b/148494302 introduces runtime encoding for unknown context which will make this possible.
- VLOG(oat) << "ClassLoaderContext check failed: uknown(null) context";
- return false;
+ if (context_ == nullptr) {
+ // When no class loader context is provided (which happens for deprecated
+ // DexFile APIs), just assume it is OK.
+ return true;
}
- size_t dir_index = oat_file_assistant_->dex_location_.rfind('/');
- std::string classpath_dir = (dir_index != std::string::npos)
- ? oat_file_assistant_->dex_location_.substr(0, dir_index)
- : "";
-
- if (!context->OpenDexFiles(classpath_dir, context_fds, /*only_read_checksums*/ true)) {
- VLOG(oat) << "ClassLoaderContext check failed: dex files from the context could not be opened";
- return false;
- }
-
- const bool result = context->VerifyClassLoaderContextMatch(file->GetClassLoaderContext()) !=
- ClassLoaderContext::VerificationResult::kMismatch;
- if (!result) {
+ ClassLoaderContext::VerificationResult matches = context_->VerifyClassLoaderContextMatch(
+ oat_file.GetClassLoaderContext(),
+ /*verify_names=*/ true,
+ /*verify_checksums=*/ true);
+ if (matches == ClassLoaderContext::VerificationResult::kMismatch) {
VLOG(oat) << "ClassLoaderContext check failed. Context was "
- << file->GetClassLoaderContext()
- << ". The expected context is " << context->EncodeContextForOatFile(classpath_dir);
+ << oat_file.GetClassLoaderContext()
+ << ". The expected context is "
+ << context_->EncodeContextForOatFile(android::base::Dirname(dex_location_));
+ return false;
}
- return result;
+ return true;
}
bool OatFileAssistant::OatFileInfo::IsExecutable() {
@@ -983,7 +964,10 @@
std::string* out_compilation_reason) {
// It may not be possible to load an oat file executable (e.g., selinux restrictions). Load
// non-executable and check the status manually.
- OatFileAssistant oat_file_assistant(filename.c_str(), isa, /*load_executable=*/ false);
+ OatFileAssistant oat_file_assistant(filename.c_str(),
+ isa,
+ /* context= */ nullptr,
+ /*load_executable=*/ false);
std::string out_odex_location; // unused
std::string out_odex_status; // unused
oat_file_assistant.GetOptimizationStatus(
@@ -1038,6 +1022,11 @@
*out_odex_status = "boot-image-more-recent";
return;
+ case kOatContextOutOfDate:
+ *out_compilation_filter = "run-from-apk-fallback";
+ *out_odex_status = "context-mismatch";
+ return;
+
case kOatDexOutOfDate:
*out_compilation_filter = "run-from-apk-fallback";
*out_odex_status = "apk-more-recent";