From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: anupritaisno1 <www.anuprita804@gmail.com>
Date: Sat, 31 Oct 2020 00:26:09 +0200
Subject: [PATCH] pass through runtime flags for exec spawning and implement
 them in the child

Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
---
 .../com/android/internal/os/ExecInit.java     |  14 +-
 core/java/com/android/internal/os/Zygote.java |   9 ++
 .../android/internal/os/ZygoteConnection.java |   2 +-
 core/jni/com_android_internal_os_Zygote.cpp   | 148 ++++++++++--------
 4 files changed, 101 insertions(+), 72 deletions(-)

diff --git a/core/java/com/android/internal/os/ExecInit.java b/core/java/com/android/internal/os/ExecInit.java
index 830e5b562a91..749c67abf389 100644
--- a/core/java/com/android/internal/os/ExecInit.java
+++ b/core/java/com/android/internal/os/ExecInit.java
@@ -31,15 +31,20 @@ public class ExecInit {
         // Parse our mandatory argument.
         int targetSdkVersion = Integer.parseInt(args[0], 10);
 
+        // Parse the runtime_flags.
+        int runtimeFlags = Integer.parseInt(args[1], 10);
+
         // Mimic system Zygote preloading.
         ZygoteInit.preload(new TimingsTraceLog("ExecInitTiming",
                 Trace.TRACE_TAG_DALVIK), false);
 
         // Launch the application.
-        String[] runtimeArgs = new String[args.length - 1];
-        System.arraycopy(args, 1, runtimeArgs, 0, runtimeArgs.length);
+        String[] runtimeArgs = new String[args.length - 2];
+        System.arraycopy(args, 2, runtimeArgs, 0, runtimeArgs.length);
         Runnable r = execInit(targetSdkVersion, runtimeArgs);
 
+        Zygote.nativeHandleRuntimeFlags(runtimeFlags);
+
         r.run();
     }
 
@@ -52,9 +57,9 @@ public class ExecInit {
      * @param args Arguments for {@link RuntimeInit#main}.
      */
     public static void execApplication(String niceName, int targetSdkVersion,
-            String instructionSet, String[] args) {
+            String instructionSet, int runtimeFlags, String[] args) {
         int niceArgs = niceName == null ? 0 : 1;
-        int baseArgs = 5 + niceArgs;
+        int baseArgs = 6 + niceArgs;
         String[] argv = new String[baseArgs + args.length];
         if (VMRuntime.is64BitInstructionSet(instructionSet)) {
             argv[0] = "/system/bin/app_process64";
@@ -68,6 +73,7 @@ public class ExecInit {
         }
         argv[3 + niceArgs] = "com.android.internal.os.ExecInit";
         argv[4 + niceArgs] = Integer.toString(targetSdkVersion);
+        argv[5 + niceArgs] = Integer.toString(runtimeFlags);
         System.arraycopy(args, 0, argv, baseArgs, args.length);
 
         WrapperInit.preserveCapabilities();
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index b1e7d15cbf4a..96b56f7bd1d6 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -1425,4 +1425,13 @@ public final class Zygote {
         }
         return runtimeFlags;
     }
+
+    /**
+     * Used on GrapheneOS to set up runtime flags
+     *
+     * @param runtimeFlags flags to be passed to the native method
+     *
+     * @hide
+     */
+    public static native void nativeHandleRuntimeFlags(int runtimeFlags);
 }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 4573cb2c0b59..9cc90f3ac142 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -539,7 +539,7 @@ class ZygoteConnection {
                 if (SystemProperties.getBoolean("sys.spawn.exec", false) &&
                         (parsedArgs.mRuntimeFlags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
                     ExecInit.execApplication(parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
-                            VMRuntime.getCurrentInstructionSet(), parsedArgs.mRemainingArgs);
+                            VMRuntime.getCurrentInstructionSet(), parsedArgs.mRuntimeFlags, parsedArgs.mRemainingArgs);
 
                     // Should not get here.
                     throw new IllegalStateException("ExecInit.execApplication unexpectedly returned");
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index c8b85c314aca..9800b24cdff5 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1721,6 +1721,80 @@ static void BindMountStorageDirs(JNIEnv* env, jobjectArray pkg_data_info_list,
   }
 }
 
+static void HandleRuntimeFlags(JNIEnv* env, jint& runtime_flags, const char* process_name, const char* nice_name_ptr) {
+    // Set process properties to enable debugging if required.
+    if ((runtime_flags & RuntimeFlags::DEBUG_ENABLE_JDWP) != 0) {
+        EnableDebugger();
+    }
+    if ((runtime_flags & RuntimeFlags::PROFILE_FROM_SHELL) != 0) {
+        // simpleperf needs the process to be dumpable to profile it.
+        if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
+            ALOGE("prctl(PR_SET_DUMPABLE) failed: %s", strerror(errno));
+            RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 1) failed");
+        }
+    }
+
+    HeapTaggingLevel heap_tagging_level;
+    switch (runtime_flags & RuntimeFlags::MEMORY_TAG_LEVEL_MASK) {
+        case RuntimeFlags::MEMORY_TAG_LEVEL_TBI:
+            heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
+            break;
+        case RuntimeFlags::MEMORY_TAG_LEVEL_ASYNC:
+            heap_tagging_level = M_HEAP_TAGGING_LEVEL_ASYNC;
+            break;
+        case RuntimeFlags::MEMORY_TAG_LEVEL_SYNC:
+            heap_tagging_level = M_HEAP_TAGGING_LEVEL_SYNC;
+            break;
+        default:
+            heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
+            break;
+    }
+    mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, heap_tagging_level);
+
+    // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART
+    // runtime.
+    runtime_flags &= ~RuntimeFlags::MEMORY_TAG_LEVEL_MASK;
+
+    // Avoid heap zero initialization for applications without MTE. Zero init may
+    // cause app compat problems, use more memory, or reduce performance. While it
+    // would be nice to have them for apps, we will have to wait until they are
+    // proven out, have more efficient hardware, and/or apply them only to new
+    // applications.
+    if (!(runtime_flags & RuntimeFlags::NATIVE_HEAP_ZERO_INIT_ENABLED)) {
+        mallopt(M_BIONIC_ZERO_INIT, 0);
+    }
+
+    // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART
+    // runtime.
+    runtime_flags &= ~RuntimeFlags::NATIVE_HEAP_ZERO_INIT_ENABLED;
+
+    if (process_name == nullptr) {
+        process_name = "zygote";
+    }
+
+    android_mallopt_gwp_asan_options_t gwp_asan_options;
+    // The system server doesn't have its nice name set by the time SpecializeCommon is called.
+    gwp_asan_options.program_name = nice_name_ptr ?: process_name;
+    switch (runtime_flags & RuntimeFlags::GWP_ASAN_LEVEL_MASK) {
+        default:
+        case RuntimeFlags::GWP_ASAN_LEVEL_NEVER:
+            gwp_asan_options.desire = Action::DONT_TURN_ON_UNLESS_OVERRIDDEN;
+            android_mallopt(M_INITIALIZE_GWP_ASAN, &gwp_asan_options, sizeof(gwp_asan_options));
+            break;
+        case RuntimeFlags::GWP_ASAN_LEVEL_ALWAYS:
+            gwp_asan_options.desire = Action::TURN_ON_FOR_APP;
+            android_mallopt(M_INITIALIZE_GWP_ASAN, &gwp_asan_options, sizeof(gwp_asan_options));
+            break;
+        case RuntimeFlags::GWP_ASAN_LEVEL_LOTTERY:
+            gwp_asan_options.desire = Action::TURN_ON_WITH_SAMPLING;
+            android_mallopt(M_INITIALIZE_GWP_ASAN, &gwp_asan_options, sizeof(gwp_asan_options));
+            break;
+    }
+    // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART
+    // runtime.
+    runtime_flags &= ~RuntimeFlags::GWP_ASAN_LEVEL_MASK;
+}
+
 // Utility routine to specialize a zygote child process.
 static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags,
                              jobjectArray rlimits, jlong permitted_capabilities,
@@ -1860,74 +1934,9 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
         }
     }
 
-    // Set process properties to enable debugging if required.
-    if ((runtime_flags & RuntimeFlags::DEBUG_ENABLE_JDWP) != 0) {
-        EnableDebugger();
-    }
-    if ((runtime_flags & RuntimeFlags::PROFILE_FROM_SHELL) != 0) {
-        // simpleperf needs the process to be dumpable to profile it.
-        if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
-            ALOGE("prctl(PR_SET_DUMPABLE) failed: %s", strerror(errno));
-            RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 1) failed");
-        }
-    }
-
-    HeapTaggingLevel heap_tagging_level;
-    switch (runtime_flags & RuntimeFlags::MEMORY_TAG_LEVEL_MASK) {
-        case RuntimeFlags::MEMORY_TAG_LEVEL_TBI:
-            heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
-            break;
-        case RuntimeFlags::MEMORY_TAG_LEVEL_ASYNC:
-            heap_tagging_level = M_HEAP_TAGGING_LEVEL_ASYNC;
-            break;
-        case RuntimeFlags::MEMORY_TAG_LEVEL_SYNC:
-            heap_tagging_level = M_HEAP_TAGGING_LEVEL_SYNC;
-            break;
-        default:
-            heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
-            break;
-    }
-    mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, heap_tagging_level);
-
-    // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART
-    // runtime.
-    runtime_flags &= ~RuntimeFlags::MEMORY_TAG_LEVEL_MASK;
-
-    // Avoid heap zero initialization for applications without MTE. Zero init may
-    // cause app compat problems, use more memory, or reduce performance. While it
-    // would be nice to have them for apps, we will have to wait until they are
-    // proven out, have more efficient hardware, and/or apply them only to new
-    // applications.
-    if (!(runtime_flags & RuntimeFlags::NATIVE_HEAP_ZERO_INIT_ENABLED)) {
-        mallopt(M_BIONIC_ZERO_INIT, 0);
-    }
-
-    // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART
-    // runtime.
-    runtime_flags &= ~RuntimeFlags::NATIVE_HEAP_ZERO_INIT_ENABLED;
-
     const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr;
-    android_mallopt_gwp_asan_options_t gwp_asan_options;
-    // The system server doesn't have its nice name set by the time SpecializeCommon is called.
-    gwp_asan_options.program_name = nice_name_ptr ?: process_name;
-    switch (runtime_flags & RuntimeFlags::GWP_ASAN_LEVEL_MASK) {
-        default:
-        case RuntimeFlags::GWP_ASAN_LEVEL_NEVER:
-            gwp_asan_options.desire = Action::DONT_TURN_ON_UNLESS_OVERRIDDEN;
-            android_mallopt(M_INITIALIZE_GWP_ASAN, &gwp_asan_options, sizeof(gwp_asan_options));
-            break;
-        case RuntimeFlags::GWP_ASAN_LEVEL_ALWAYS:
-            gwp_asan_options.desire = Action::TURN_ON_FOR_APP;
-            android_mallopt(M_INITIALIZE_GWP_ASAN, &gwp_asan_options, sizeof(gwp_asan_options));
-            break;
-        case RuntimeFlags::GWP_ASAN_LEVEL_LOTTERY:
-            gwp_asan_options.desire = Action::TURN_ON_WITH_SAMPLING;
-            android_mallopt(M_INITIALIZE_GWP_ASAN, &gwp_asan_options, sizeof(gwp_asan_options));
-            break;
-    }
-    // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART
-    // runtime.
-    runtime_flags &= ~RuntimeFlags::GWP_ASAN_LEVEL_MASK;
+
+    HandleRuntimeFlags(env, runtime_flags, process_name, nice_name_ptr);
 
     SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities,
                     fail_fn);
@@ -2821,6 +2830,10 @@ static void com_android_internal_os_Zygote_nativeAllowFilesOpenedByPreload(JNIEn
     gPreloadFdsExtracted = true;
 }
 
+static void nativeHandleRuntimeFlagsWrapper(JNIEnv* env, jclass, jint runtime_flags) {
+    HandleRuntimeFlags(env, runtime_flags, nullptr, nullptr);
+}
+
 static const JNINativeMethod gMethods[] = {
         {"nativeForkAndSpecialize",
          "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/"
@@ -2873,6 +2886,7 @@ static const JNINativeMethod gMethods[] = {
          (void*)com_android_internal_os_Zygote_nativeMarkOpenedFilesBeforePreload},
         {"nativeAllowFilesOpenedByPreload", "()V",
          (void*)com_android_internal_os_Zygote_nativeAllowFilesOpenedByPreload},
+        {"nativeHandleRuntimeFlags", "(I)V", (void*)nativeHandleRuntimeFlagsWrapper},
 };
 
 int register_com_android_internal_os_Zygote(JNIEnv* env) {
