Transient SELinux domain for system_server JIT

Create a transient SELinux domain where system_server can perform
certain JIT setup. The idea is that system_server will start in the
system_server_startup domain, setup certain JIT pages, then perform a
one-way transition into the system_server domain. From that point,
further JITing operations are disallowed.

Bug: 62356545
Test: device boots, no permission errors
Change-Id: Ic55b2cc5aba420ebcf62736622e08881a4779004
diff --git a/private/domain.te b/private/domain.te
index 7945d89..8e3c4e6 100644
--- a/private/domain.te
+++ b/private/domain.te
@@ -175,3 +175,38 @@
   -init
   -installd
 } { privapp_data_file app_data_file }:dir_file_class_set { relabelfrom relabelto };
+
+neverallow {
+    domain
+    -appdomain # for oemfs
+    -bootanim # for oemfs
+    -recovery # for /tmp/update_binary in tmpfs
+} { fs_type -rootfs }:file execute;
+
+#
+# Assert that, to the extent possible, we're not loading executable content from
+# outside the rootfs or /system partition except for a few whitelisted domains.
+# Executable files loaded from /data is a persistence vector
+# we want to avoid. See
+# https://bugs.chromium.org/p/project-zero/issues/detail?id=955 for example.
+#
+neverallow {
+    domain
+    -appdomain
+    with_asan(`-asan_extract')
+    -shell
+    userdebug_or_eng(`-su')
+    -system_server_startup # for memfd backed executable regions
+    -webview_zygote
+    -zygote
+    userdebug_or_eng(`-mediaextractor')
+    userdebug_or_eng(`-mediaswcodec')
+} {
+    file_type
+    -system_file_type
+    -system_lib_file
+    -system_linker_exec
+    -vendor_file_type
+    -exec_type
+    -postinstall_file
+}:file execute;
diff --git a/private/seapp_contexts b/private/seapp_contexts
index 418150e..d0cf2a5 100644
--- a/private/seapp_contexts
+++ b/private/seapp_contexts
@@ -98,7 +98,8 @@
 # Ephemeral Apps must run in the ephemeral_app domain
 neverallow isEphemeralApp=true domain=((?!ephemeral_app).)*
 
-isSystemServer=true domain=system_server
+isSystemServer=true domain=system_server_startup
+
 user=_app seinfo=platform name=com.android.traceur domain=traceur_app type=app_data_file levelFrom=all
 user=system seinfo=platform domain=system_app type=system_app_data_file
 user=bluetooth seinfo=platform domain=bluetooth type=bluetooth_data_file
diff --git a/private/system_server.te b/private/system_server.te
index 42a89d4..506378e 100644
--- a/private/system_server.te
+++ b/private/system_server.te
@@ -912,6 +912,11 @@
 # TODO: deal with tmpfs_domain pub/priv split properly
 neverallow system_server system_server_tmpfs:file execute;
 
+# Resources handed off by system_server_startup
+allow system_server system_server_startup:fd use;
+allow system_server system_server_startup_tmpfs:file { read write map };
+allow system_server system_server_startup:unix_dgram_socket write;
+
 # dexoptanalyzer is currently used only for secondary dex files which
 # system_server should never access.
 neverallow system_server dexoptanalyzer_exec:file no_x_file_perms;
diff --git a/private/system_server_startup.te b/private/system_server_startup.te
new file mode 100644
index 0000000..4bd10c8
--- /dev/null
+++ b/private/system_server_startup.te
@@ -0,0 +1,12 @@
+type system_server_startup, domain, coredomain;
+
+tmpfs_domain(system_server_startup)
+
+# Create JIT memory
+allow system_server_startup self:process execmem;
+allow system_server_startup system_server_startup_tmpfs:file { execute read write open map };
+
+# Allow system_server_startup to run setcon() and enter the
+# system_server domain
+allow system_server_startup self:process setcurrent;
+allow system_server_startup system_server:process dyntransition;
diff --git a/private/zygote.te b/private/zygote.te
index 0e21d51..491f079 100644
--- a/private/zygote.te
+++ b/private/zygote.te
@@ -14,7 +14,7 @@
 
 # Switch SELinux context to app domains.
 allow zygote self:process setcurrent;
-allow zygote system_server:process dyntransition;
+allow zygote system_server_startup:process dyntransition;
 allow zygote appdomain:process dyntransition;
 allow zygote webview_zygote:process dyntransition;
 
@@ -132,8 +132,12 @@
 # written on appdomain are applied to all app processes.
 # This is achieved by ensuring that it is impossible for zygote to
 # setcon (dyntransition) to any types other than those associated
-# with appdomain plus system_server and webview_zygote.
-neverallow zygote ~{ appdomain system_server webview_zygote }:process dyntransition;
+# with appdomain plus system_server_startup and webview_zygote.
+neverallow zygote ~{
+  appdomain
+  system_server_startup
+  webview_zygote
+}:process dyntransition;
 
 # Zygote should never execute anything from /data except for /data/dalvik-cache files.
 neverallow zygote {
diff --git a/public/domain.te b/public/domain.te
index dcd12b1..89f1635 100644
--- a/public/domain.te
+++ b/public/domain.te
@@ -476,40 +476,6 @@
 # this capability, including device-specific domains.
 neverallow { domain -kernel -init -recovery -vold -zygote -update_engine -otapreopt_chroot -apexd } { fs_type -sdcard_type }:filesystem { mount remount relabelfrom relabelto };
 
-#
-# Assert that, to the extent possible, we're not loading executable content from
-# outside the rootfs or /system partition except for a few whitelisted domains.
-# Executable files loaded from /data is a persistence vector
-# we want to avoid. See
-# https://bugs.chromium.org/p/project-zero/issues/detail?id=955 for example.
-#
-neverallow {
-    domain
-    -appdomain
-    with_asan(`-asan_extract')
-    -shell
-    userdebug_or_eng(`-su')
-    -webview_zygote
-    -zygote
-    userdebug_or_eng(`-mediaextractor')
-    userdebug_or_eng(`-mediaswcodec')
-} {
-    file_type
-    -system_file_type
-    -system_lib_file
-    -system_linker_exec
-    -vendor_file_type
-    -exec_type
-    -postinstall_file
-}:file execute;
-
-neverallow {
-    domain
-    -appdomain # for oemfs
-    -bootanim # for oemfs
-    -recovery # for /tmp/update_binary in tmpfs
-} { fs_type -rootfs }:file execute;
-
 # Files from cache should never be executed
 neverallow domain { cache_file cache_backup_file cache_private_backup_file cache_recovery_file }:file execute;