Change only_use_system_oat_files_ logic.

If we're creating a process which is a zygote, set it to true. Change it
to false on non-system-server fork.

This makes sure that zygote doesn't load oat files from /data, which
would then make system server abort at startup.

Test: 677-fsi, 677-fsi2
Bug: 198531508
Change-Id: I367fcf79f2e60a32457829ddc88b680fc2d00099
diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc
index c6c1b50..884bca1 100644
--- a/libartbase/base/file_utils.cc
+++ b/libartbase/base/file_utils.cc
@@ -644,14 +644,12 @@
   LOG(FATAL) << "LocationIsOnSystem is unsupported on Windows.";
   return false;
 #else
-  UniqueCPtr<const char[]> full_path(realpath(location.c_str(), nullptr));
-  return full_path != nullptr &&
-      android::base::StartsWith(full_path.get(), GetAndroidRoot().c_str());
+  return android::base::StartsWith(location, GetAndroidRoot().c_str());
 #endif
 }
 
 bool LocationIsTrusted(const std::string& location, bool trust_art_apex_data_files) {
-  if (LocationIsOnSystem(location)) {
+  if (LocationIsOnSystem(location) || LocationIsOnArtModule(location)) {
     return true;
   }
   return LocationIsOnArtApexData(location) & trust_art_apex_data_files;
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index e8069d9..eae7c20 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -316,10 +316,10 @@
     runtime_flags &= ~DISABLE_VERIFIER;
   }
 
-  if ((runtime_flags & ONLY_USE_TRUSTED_OAT_FILES) != 0 || is_system_server) {
-    runtime->GetOatFileManager().SetOnlyUseTrustedOatFiles();
-    runtime_flags &= ~ONLY_USE_TRUSTED_OAT_FILES;
+  if ((runtime_flags & ONLY_USE_TRUSTED_OAT_FILES) == 0 && !is_system_server) {
+    runtime->GetOatFileManager().ClearOnlyUseTrustedOatFiles();
   }
+  runtime_flags &= ~ONLY_USE_TRUSTED_OAT_FILES;
 
   api_enforcement_policy = hiddenapi::EnforcementPolicyFromInt(
       (runtime_flags & HIDDEN_API_ENFORCEMENT_POLICY_MASK) >> API_ENFORCEMENT_POLICY_SHIFT);
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 921c6d2..64d039a 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -65,16 +65,19 @@
 // If true, we attempt to load the application image if it exists.
 static constexpr bool kEnableAppImage = true;
 
-const OatFile* OatFileManager::RegisterOatFile(std::unique_ptr<const OatFile> oat_file) {
+const OatFile* OatFileManager::RegisterOatFile(std::unique_ptr<const OatFile> oat_file,
+                                               bool in_memory) {
   // Use class_linker vlog to match the log for dex file registration.
   VLOG(class_linker) << "Registered oat file " << oat_file->GetLocation();
   PaletteNotifyOatFileLoaded(oat_file->GetLocation().c_str());
 
   WriterMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
-  CHECK(!only_use_system_oat_files_ ||
+  CHECK(in_memory ||
+        !only_use_system_oat_files_ ||
         LocationIsTrusted(oat_file->GetLocation(), !Runtime::Current()->DenyArtApexDataFiles()) ||
         !oat_file->IsExecutable())
-      << "Registering a non /system oat file: " << oat_file->GetLocation();
+      << "Registering a non /system oat file: " << oat_file->GetLocation() << " android-root="
+      << GetAndroidRoot();
   DCHECK(oat_file != nullptr);
   if (kIsDebugBuild) {
     CHECK(oat_files_.find(oat_file) == oat_files_.end());
@@ -155,7 +158,9 @@
   std::vector<const OatFile*> oat_files;
   oat_files.reserve(spaces.size());
   for (gc::space::ImageSpace* space : spaces) {
-    oat_files.push_back(RegisterOatFile(space->ReleaseOatFile()));
+    // The oat file was generated in memory if the image space has a profile.
+    bool in_memory = !space->GetProfileFile().empty();
+    oat_files.push_back(RegisterOatFile(space->ReleaseOatFile(), in_memory));
   }
   return oat_files;
 }
@@ -795,29 +800,14 @@
   }
 }
 
+void OatFileManager::ClearOnlyUseTrustedOatFiles() {
+  only_use_system_oat_files_ = false;
+}
+
 void OatFileManager::SetOnlyUseTrustedOatFiles() {
   ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
-  // Make sure all files that were loaded up to this point are on /system.
-  // Skip the image files as they can encode locations that don't exist (eg not
-  // containing the arch in the path, or for JIT zygote /nonx/existent).
-  std::vector<const OatFile*> boot_vector = GetBootOatFiles();
-  std::unordered_set<const OatFile*> boot_set(boot_vector.begin(), boot_vector.end());
-
-  for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
-    if (boot_set.find(oat_file.get()) == boot_set.end()) {
-      // This method is called during runtime initialization before we can call
-      // Runtime::Current()->DenyArtApexDataFiles(). Since we don't want to fail hard if
-      // the ART APEX data files are untrusted, just treat them as trusted for the check here.
-      const bool trust_art_apex_data_files = true;
-      if (!LocationIsTrusted(oat_file->GetLocation(), trust_art_apex_data_files)) {
-        // When the file is not in a trusted location, we check whether the oat file has any
-        // AOT or DEX code. It is a fatal error if it has.
-        if (CompilerFilter::IsAotCompilationEnabled(oat_file->GetCompilerFilter()) ||
-            oat_file->ContainsDexCode()) {
-          LOG(FATAL) << "Executing untrusted code from " << oat_file->GetLocation();
-        }
-      }
-    }
+  if (!oat_files_.empty()) {
+    LOG(FATAL) << "Unexpected non-empty loaded oat files ";
   }
   only_use_system_oat_files_ = true;
 }
diff --git a/runtime/oat_file_manager.h b/runtime/oat_file_manager.h
index abf4ea0..0c1a69b 100644
--- a/runtime/oat_file_manager.h
+++ b/runtime/oat_file_manager.h
@@ -53,7 +53,9 @@
 
   // Add an oat file to the internal accounting, std::aborts if there already exists an oat file
   // with the same base address. Returns the oat file pointer from oat_file.
-  const OatFile* RegisterOatFile(std::unique_ptr<const OatFile> oat_file)
+  // The `in_memory` parameter is whether the oat file is not present on disk,
+  // but only in memory (for example files created with memfd).
+  const OatFile* RegisterOatFile(std::unique_ptr<const OatFile> oat_file, bool in_memory = false)
       REQUIRES(!Locks::oat_file_manager_lock_);
 
   void UnRegisterAndDeleteOatFile(const OatFile* oat_file)
@@ -119,6 +121,7 @@
   void DumpForSigQuit(std::ostream& os);
 
   void SetOnlyUseTrustedOatFiles();
+  void ClearOnlyUseTrustedOatFiles();
 
   // Spawn a background thread which verifies all classes in the given dex files.
   void RunBackgroundVerification(const std::vector<const DexFile*>& dex_files,
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 6eaa435..8dbed9b 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1390,9 +1390,9 @@
 
   QuasiAtomic::Startup();
 
-  oat_file_manager_ = new OatFileManager;
+  oat_file_manager_ = new OatFileManager();
 
-  jni_id_manager_.reset(new jni::JniIdManager);
+  jni_id_manager_.reset(new jni::JniIdManager());
 
   Thread::SetSensitiveThreadHook(runtime_options.GetOrDefault(Opt::HookIsSensitiveThread));
   Monitor::Init(runtime_options.GetOrDefault(Opt::LockProfThreshold),
@@ -1438,6 +1438,10 @@
   image_dex2oat_enabled_ = runtime_options.GetOrDefault(Opt::ImageDex2Oat);
   dump_native_stack_on_sig_quit_ = runtime_options.GetOrDefault(Opt::DumpNativeStackOnSigQuit);
 
+  if (is_zygote_ || runtime_options.Exists(Opt::OnlyUseTrustedOatFiles)) {
+    oat_file_manager_->SetOnlyUseTrustedOatFiles();
+  }
+
   vfprintf_ = runtime_options.GetOrDefault(Opt::HookVfprintf);
   exit_ = runtime_options.GetOrDefault(Opt::HookExit);
   abort_ = runtime_options.GetOrDefault(Opt::HookAbort);
@@ -1981,11 +1985,6 @@
 
   VLOG(startup) << "Runtime::Init exiting";
 
-  // Set OnlyUseTrustedOatFiles only after the boot classpath has been set up.
-  if (runtime_options.Exists(Opt::OnlyUseTrustedOatFiles)) {
-    oat_file_manager_->SetOnlyUseTrustedOatFiles();
-  }
-
   return true;
 }
 
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 6d89720..b94c475 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -906,6 +906,8 @@
 
 linkdirs() {
   find "$1" -maxdepth 1 -mindepth 1 -type d | xargs -i ln -sf '{}' "$2"
+  # Also create a link for the boot image.
+  ln -sf $ANDROID_HOST_OUT/apex/art_boot_images "$2"
 }
 
 if [ "$CREATE_ANDROID_ROOT" = "y" ]; then
@@ -915,6 +917,8 @@
     # TODO Make this overlay more generic.
     linkroot_overlay_cmdline="linkdirs $OUT_DIR/soong/host/linux_bionic-x86 ${ANDROID_ROOT}"
   fi
+  # Replace the boot image to a location expected by the runtime.
+  DALVIKVM_BOOT_OPT="-Ximage:${ANDROID_ROOT}/art_boot_images/javalib/boot.art"
 fi
 
 if [ "$USE_ZIPAPEX" = "y" ]; then