Revert^2 "Enforce files loaded in DexFile to be read-only"

17a8be6ce9d2bbe5b4c75296e3ae30885819f4ee

Change-Id: I0a53b50f8781a2809d6fad5719d67dd91aeebb72
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index d714206..306198f 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -57,6 +57,9 @@
 
 namespace art {
 
+// Should be the same as dalvik.system.DexFile.ENFORCE_READ_ONLY_JAVA_DCL
+static constexpr uint64_t kEnforceReadOnlyJavaDcl = 218865702;
+
 using android::base::StringPrintf;
 
 static bool ConvertJavaArrayToDexFiles(
@@ -316,6 +319,32 @@
     return nullptr;
   }
 
+#ifdef __ANDROID__
+  const int uid = getuid();
+  // The following UIDs are exempted:
+  // * Root (0): root processes always have write access to files.
+  // * System (1000): /data/app/**.apk are owned by AID_SYSTEM;
+  //   loading installed APKs in system_server is allowed.
+  // * Shell (2000): directly calling dalvikvm/app_process in ADB shell
+  //   to run JARs with CLI is allowed.
+  if (uid != 0 && uid != 1000 && uid != 2000) {
+    Runtime* const runtime = Runtime::Current();
+    CompatFramework& compatFramework = runtime->GetCompatFramework();
+    if (compatFramework.IsChangeEnabled(kEnforceReadOnlyJavaDcl)) {
+      if (access(sourceName.c_str(), W_OK) == 0) {
+        LOG(ERROR) << "Attempt to load writable dex file: " << sourceName.c_str();
+        ScopedLocalRef<jclass> se(env, env->FindClass("java/lang/SecurityException"));
+        std::string message(
+            StringPrintf("Writable dex file '%s' is not allowed.", sourceName.c_str()));
+        env->ThrowNew(se.get(), message.c_str());
+        return nullptr;
+      }
+    }
+  }
+#else
+  (void) kEnforceReadOnlyJavaDcl;
+#endif
+
   std::vector<std::string> error_msgs;
   const OatFile* oat_file = nullptr;
   std::vector<std::unique_ptr<const DexFile>> dex_files =