Handle new zygote flags in ART
Add support for DISABLE_VERIFIER and ONLY_USE_SYSTEM_OAT_FILES.
bug: 30972906
bug: 63920015
Test: device boots
Change-Id: I7c4eddc070908aed980d54d374c0b261d1f32d57
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index d767e98..e40a071 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -31,6 +31,8 @@
#include "nativehelper/JNIHelp.h"
#include "nativehelper/ScopedUtfChars.h"
#include "non_debuggable_classes.h"
+#include "oat_file.h"
+#include "oat_file_manager.h"
#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread-current-inl.h"
@@ -154,20 +156,22 @@
}
}
-static void EnableDebugFeatures(uint32_t runtime_flags) {
- // Must match values in com.android.internal.os.Zygote.
- enum {
- DEBUG_ENABLE_JDWP = 1,
- DEBUG_ENABLE_CHECKJNI = 1 << 1,
- DEBUG_ENABLE_ASSERT = 1 << 2,
- DEBUG_ENABLE_SAFEMODE = 1 << 3,
- DEBUG_ENABLE_JNI_LOGGING = 1 << 4,
- DEBUG_GENERATE_DEBUG_INFO = 1 << 5,
- DEBUG_ALWAYS_JIT = 1 << 6,
- DEBUG_NATIVE_DEBUGGABLE = 1 << 7,
- DEBUG_JAVA_DEBUGGABLE = 1 << 8,
- };
+// Must match values in com.android.internal.os.Zygote.
+enum {
+ DEBUG_ENABLE_JDWP = 1,
+ DEBUG_ENABLE_CHECKJNI = 1 << 1,
+ DEBUG_ENABLE_ASSERT = 1 << 2,
+ DEBUG_ENABLE_SAFEMODE = 1 << 3,
+ DEBUG_ENABLE_JNI_LOGGING = 1 << 4,
+ DEBUG_GENERATE_DEBUG_INFO = 1 << 5,
+ DEBUG_ALWAYS_JIT = 1 << 6,
+ DEBUG_NATIVE_DEBUGGABLE = 1 << 7,
+ DEBUG_JAVA_DEBUGGABLE = 1 << 8,
+ DISABLE_VERIFIER = 1 << 9,
+ ONLY_USE_SYSTEM_OAT_FILES = 1 << 10,
+};
+static uint32_t EnableDebugFeatures(uint32_t runtime_flags) {
Runtime* const runtime = Runtime::Current();
if ((runtime_flags & DEBUG_ENABLE_CHECKJNI) != 0) {
JavaVMExt* vm = runtime->GetJavaVM();
@@ -237,9 +241,7 @@
runtime_flags &= ~DEBUG_NATIVE_DEBUGGABLE;
}
- if (runtime_flags != 0) {
- LOG(ERROR) << StringPrintf("Unknown bits set in runtime_flags: %#x", runtime_flags);
- }
+ return runtime_flags;
}
static jlong ZygoteHooks_nativePreFork(JNIEnv* env, jclass) {
@@ -266,7 +268,21 @@
Thread* thread = reinterpret_cast<Thread*>(token);
// Our system thread ID, etc, has changed so reset Thread state.
thread->InitAfterFork();
- EnableDebugFeatures(runtime_flags);
+ runtime_flags = EnableDebugFeatures(runtime_flags);
+
+ if ((runtime_flags & DISABLE_VERIFIER) != 0) {
+ Runtime::Current()->DisableVerifier();
+ runtime_flags &= ~DISABLE_VERIFIER;
+ }
+
+ if ((runtime_flags & ONLY_USE_SYSTEM_OAT_FILES) != 0) {
+ Runtime::Current()->GetOatFileManager().SetOnlyUseSystemOatFiles();
+ runtime_flags &= ~ONLY_USE_SYSTEM_OAT_FILES;
+ }
+
+ if (runtime_flags != 0) {
+ LOG(ERROR) << StringPrintf("Unknown bits set in runtime_flags: %#x", runtime_flags);
+ }
// Update tracing.
if (Trace::GetMethodTracingMode() != TracingMode::kTracingInactive) {
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 516c833..05b63d2 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -21,6 +21,7 @@
#include <vector>
#include "android-base/stringprintf.h"
+#include "android-base/strings.h"
#include "art_field-inl.h"
#include "base/bit_vector-inl.h"
@@ -51,8 +52,15 @@
// If true, we attempt to load the application image if it exists.
static constexpr bool kEnableAppImage = true;
+static bool OatFileIsOnSystem(const std::unique_ptr<const OatFile>& oat_file) {
+ UniqueCPtr<const char[]> path(realpath(oat_file->GetLocation().c_str(), nullptr));
+ return path != nullptr && android::base::StartsWith(oat_file->GetLocation(), GetAndroidRoot());
+}
+
const OatFile* OatFileManager::RegisterOatFile(std::unique_ptr<const OatFile> oat_file) {
WriterMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
+ CHECK(!only_use_system_oat_files_ || OatFileIsOnSystem(oat_file))
+ << "Registering a non /system oat file: " << oat_file->GetLocation();
DCHECK(oat_file != nullptr);
if (kIsDebugBuild) {
CHECK(oat_files_.find(oat_file) == oat_files_.end());
@@ -421,7 +429,8 @@
const OatFile* source_oat_file = nullptr;
- if (!oat_file_assistant.IsUpToDate()) {
+ // No point in trying to make up-to-date if we can only use system oat files.
+ if (!only_use_system_oat_files_ && !oat_file_assistant.IsUpToDate()) {
// Update the oat file on disk if we can, based on the --compiler-filter
// option derived from the current runtime options.
// This may fail, but that's okay. Best effort is all that matters here.
@@ -447,10 +456,12 @@
// Get the oat file on disk.
std::unique_ptr<const OatFile> oat_file(oat_file_assistant.GetBestOatFile().release());
- // Prevent oat files from being loaded if no class_loader or dex_elements are provided.
- // This can happen when the deprecated DexFile.<init>(String) is called directly, and it
- // could load oat files without checking the classpath, which would be incorrect.
- if ((class_loader != nullptr || dex_elements != nullptr) && oat_file != nullptr) {
+ if (oat_file != nullptr && only_use_system_oat_files_ && !OatFileIsOnSystem(oat_file)) {
+ // If the oat file is not on /system, don't use it.
+ } else if ((class_loader != nullptr || dex_elements != nullptr) && oat_file != nullptr) {
+ // Prevent oat files from being loaded if no class_loader or dex_elements are provided.
+ // This can happen when the deprecated DexFile.<init>(String) is called directly, and it
+ // could load oat files without checking the classpath, which would be incorrect.
// Take the file only if it has no collisions, or we must take it because of preopting.
bool accept_oat_file =
!HasCollisions(oat_file.get(), context.get(), /*out*/ &error_msg);
@@ -597,6 +608,12 @@
return dex_files;
}
+void OatFileManager::SetOnlyUseSystemOatFiles() {
+ ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
+ CHECK_EQ(oat_files_.size(), GetBootOatFiles().size());
+ only_use_system_oat_files_ = true;
+}
+
void OatFileManager::DumpForSigQuit(std::ostream& os) {
ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
std::vector<const OatFile*> boot_oat_files = GetBootOatFiles();
diff --git a/runtime/oat_file_manager.h b/runtime/oat_file_manager.h
index 4523494..1205773 100644
--- a/runtime/oat_file_manager.h
+++ b/runtime/oat_file_manager.h
@@ -45,7 +45,7 @@
// pointers returned from functions are always valid.
class OatFileManager {
public:
- OatFileManager() : have_non_pic_oat_file_(false) {}
+ OatFileManager() : have_non_pic_oat_file_(false), only_use_system_oat_files_(false) {}
~OatFileManager();
// Add an oat file to the internal accounting, std::aborts if there already exists an oat file
@@ -105,6 +105,8 @@
void DumpForSigQuit(std::ostream& os);
+ void SetOnlyUseSystemOatFiles();
+
private:
// Check that the class loader context of the given oat file matches the given context.
// This will perform a check that all class loaders in the chain have the same type and
@@ -125,6 +127,7 @@
std::set<std::unique_ptr<const OatFile>> oat_files_ GUARDED_BY(Locks::oat_file_manager_lock_);
bool have_non_pic_oat_file_;
+ bool only_use_system_oat_files_;
DISALLOW_COPY_AND_ASSIGN(OatFileManager);
};
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 5888762..c68c341 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -2330,6 +2330,10 @@
}
}
+void Runtime::DisableVerifier() {
+ verify_ = verifier::VerifyMode::kNone;
+}
+
bool Runtime::IsVerificationEnabled() const {
return verify_ == verifier::VerifyMode::kEnable ||
verify_ == verifier::VerifyMode::kSoftFail;
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 2eb4411..399e1c1 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -514,6 +514,7 @@
return !implicit_so_checks_;
}
+ void DisableVerifier();
bool IsVerificationEnabled() const;
bool IsVerificationSoftFail() const;