Reland: Move zygote's seccomp setup to post-fork

Before this change, seccomp filter setup is as early as in zygote's main
function.  To make it possible to split app and system server's filter,
this postpone the setup to after fork.  It also starts to call app
specific and system server specific setup function.

The filter setup is done in Zygote's ForkAndSpecializeCommon.  This is
because adding a seccomp filter must be done when either the caller has
CAP_SYS_ADMIN or after the PR_SET_NO_NEW_PRIVS bit is set.  Given that
setting PR_SET_NO_NEW_PRIVS breaks SELinux domain transition
(b/71859146), this must be done after Zygote forks but before
CAP_SYS_ADMIN is droppped.

Test: (cts) -m CtsSecurityTestCases -t android.security.cts.SeccompTest
Test: no selinux denial flood in dmesg with selinux enforced
Test: debuggerd -b `pidof com.android.phone`  # logcat shows tombstoned
      received crash request
Bug: 63944145
Bug: 71859146

Change-Id: I8215c8530d3d0de504a270488f8e29635805e8b0
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 32ef3dc..63dba43 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -53,6 +53,7 @@
 #include <private/android_filesystem_config.h>
 #include <utils/String8.h>
 #include <selinux/android.h>
+#include <seccomp_policy.h>
 #include <processgroup/processgroup.h>
 
 #include "core_jni_helpers.h"
@@ -76,6 +77,8 @@
 static jclass gZygoteClass;
 static jmethodID gCallPostForkChildHooks;
 
+static bool g_is_security_enforced = true;
+
 // Must match values in com.android.internal.os.Zygote.
 enum MountExternalKind {
   MOUNT_EXTERNAL_NONE = 0,
@@ -229,6 +232,20 @@
   mallopt(M_DECAY_TIME, 1);
 }
 
+static void SetUpSeccompFilter(uid_t uid) {
+  if (!g_is_security_enforced) {
+    ALOGI("seccomp disabled by setenforce 0");
+    return;
+  }
+
+  // Apply system or app filter based on uid.
+  if (getuid() >= AID_APP_START) {
+    set_app_seccomp_filter();
+  } else {
+    set_system_seccomp_filter();
+  }
+}
+
 static void EnableKeepCapabilities(JNIEnv* env) {
   int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
   if (rc == -1) {
@@ -541,6 +558,11 @@
       RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
     }
 
+    // Must be called when the new process still has CAP_SYS_ADMIN.  The other alternative is to
+    // call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that breaks SELinux domain transition (see
+    // b/71859146).
+    SetUpSeccompFilter(uid);
+
     // Keep capabilities across UID change, unless we're staying root.
     if (uid != 0) {
       EnableKeepCapabilities(env);
@@ -698,6 +720,12 @@
 
 namespace android {
 
+static void com_android_internal_os_Zygote_nativeSecurityInit(JNIEnv*, jclass) {
+  // security_getenforce is not allowed on app process. Initialize and cache the value before
+  // zygote forks.
+  g_is_security_enforced = security_getenforce();
+}
+
 static void com_android_internal_os_Zygote_nativePreApplicationInit(JNIEnv*, jclass) {
   PreApplicationInit();
 }
@@ -832,6 +860,8 @@
 }
 
 static const JNINativeMethod gMethods[] = {
+    { "nativeSecurityInit", "()V",
+      (void *) com_android_internal_os_Zygote_nativeSecurityInit },
     { "nativeForkAndSpecialize",
       "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },