Permissions for odrefresh and /data/misc/apexdata/com.android.art

odrefresh is the process responsible for checking and creating ART
compilation artifacts that live in the ART APEX data
directory (/data/misc/apexdata/com.android.art).

There are two types of change here:

1) enabling odrefresh to run dex2oat and write updated boot class path
   and system server AOT artifacts into the ART APEX data directory.

2) enabling the zygote and assorted diagnostic tools to use the
   updated AOT artifacts.

odrefresh uses two file contexts: apex_art_data_file and
apex_art_staging_data_file. When odrefresh invokes dex2oat, the
generated files have the apex_art_staging_data_file label (which allows
writing). odrefresh then moves these files from the staging area to
their installation area and gives them the apex_art_data_file label.

Bug: 160683548
Test: adb root && adb shell /apex/com.android.art/bin/odrefresh
Change-Id: I9fa290e0c9c1b7b82be4dacb9f2f8cb8c11e4895
diff --git a/private/apexd.te b/private/apexd.te
index 417504b..c3da0fe 100644
--- a/private/apexd.te
+++ b/private/apexd.te
@@ -12,6 +12,8 @@
 allow apexd apex_metadata_file:file create_file_perms;
 
 # Allow apexd to create files and directories for snapshots of apex data
+allow apexd apex_art_data_file:dir { create_dir_perms relabelto };
+allow apexd apex_art_data_file:file { create_file_perms relabelto };
 allow apexd apex_permission_data_file:dir { create_dir_perms relabelto };
 allow apexd apex_permission_data_file:file { create_file_perms relabelto };
 allow apexd apex_module_data_file:dir { create_dir_perms relabelfrom };
diff --git a/private/app.te b/private/app.te
index dacea29..30ef991 100644
--- a/private/app.te
+++ b/private/app.te
@@ -62,3 +62,25 @@
 
 # Allow to read db.log.detailed, db.log.slow_query_threshold*
 get_prop(appdomain, sqlite_log_prop)
+
+# Read /data/misc/apexdata/com.android.art
+allow appdomain { apex_art_data_file apex_module_data_file }:dir search;
+allow appdomain apex_art_data_file:file r_file_perms;
+
+# Sensitive app domains are not allowed to execute from /data
+# to prevent persistence attacks and ensure all code is executed
+# from read-only locations.
+neverallow {
+  bluetooth
+  isolated_app
+  nfc
+  radio
+  shared_relro
+  system_app
+} {
+  data_file_type
+  -apex_art_data_file
+  -dalvikcache_data_file
+  -system_data_file # shared libs in apks
+  -apk_data_file
+}:file no_x_file_perms;
diff --git a/private/compat/30.0/30.0.ignore.cil b/private/compat/30.0/30.0.ignore.cil
index adb1020..d5f2789 100644
--- a/private/compat/30.0/30.0.ignore.cil
+++ b/private/compat/30.0/30.0.ignore.cil
@@ -8,6 +8,8 @@
     ab_update_gki_prop
     adbd_config_prop
     apc_service
+    apex_art_data_file
+    apex_art_staging_data_file
     apex_info_file
     cgroup_desc_api_file
     cgroup_v2
@@ -44,6 +46,8 @@
     mediatranscoding_tmpfs
     music_recognition_service
     nfc_logs_data_file
+    odrefresh
+    odrefresh_exec
     people_service
     persist_vendor_debug_wifi_prop
     power_debug_prop
diff --git a/private/crash_dump.te b/private/crash_dump.te
index f130327..616f00c 100644
--- a/private/crash_dump.te
+++ b/private/crash_dump.te
@@ -47,3 +47,7 @@
 
 neverallow crash_dump self:process ptrace;
 neverallow crash_dump gpu_device:chr_file *;
+
+# Read ART APEX data directory
+allow crash_dump apex_art_data_file:dir { getattr search };
+allow crash_dump apex_art_data_file:file r_file_perms;
diff --git a/private/dex2oat.te b/private/dex2oat.te
index 50e43ad..27e4b0c 100644
--- a/private/dex2oat.te
+++ b/private/dex2oat.te
@@ -32,6 +32,21 @@
 # the framework.
 allow dex2oat { privapp_data_file app_data_file }:file { getattr read write lock map };
 
+# Allow dex2oat to find files and directories under /data/misc/apexdata/com.android.runtime.
+allow dex2oat apex_module_data_file:dir search;
+
+# Allow dex2oat to use file descriptors passed from odrefresh.
+allow dex2oat odrefresh:fd use;
+
+# Allow dex2oat to write to file descriptors from odrefresh for files
+# in the staging area.
+allow dex2oat apex_art_staging_data_file:dir r_dir_perms;
+allow dex2oat apex_art_staging_data_file:file { getattr map read write unlink };
+
+# Allow dex2oat to read artifacts from odrefresh.
+allow dex2oat apex_art_data_file:dir r_dir_perms;
+allow dex2oat apex_art_data_file:file r_file_perms;
+
 ##################
 # A/B OTA Dexopt #
 ##################
diff --git a/private/dexoptanalyzer.te b/private/dexoptanalyzer.te
index b8b7b30..d5728d1 100644
--- a/private/dexoptanalyzer.te
+++ b/private/dexoptanalyzer.te
@@ -14,12 +14,21 @@
 # processes.
 tmpfs_domain(dexoptanalyzer)
 
-# Read symlinks in /data/dalvik-cache. This is required for PIC mode boot
-# app_data_file the oat file is symlinked to the original file in /system.
+# Allow dexoptanalyzer to read files in the dalvik cache.
 allow dexoptanalyzer dalvikcache_data_file:dir { getattr search };
 allow dexoptanalyzer dalvikcache_data_file:file r_file_perms;
+
+# Read symlinks in /data/dalvik-cache. This is required for PIC mode boot
+# app_data_file the oat file is symlinked to the original file in /system.
 allow dexoptanalyzer dalvikcache_data_file:lnk_file read;
 
+# Allow dexoptanalyzer to read files in the ART APEX data directory.
+allow dexoptanalyzer { apex_art_data_file apex_module_data_file }:dir { getattr search };
+allow dexoptanalyzer apex_art_data_file:file r_file_perms;
+
+# Allow dexoptanalyzer to use file descriptors from odrefresh.
+allow dexoptanalyzer odrefresh:fd use;
+
 allow dexoptanalyzer installd:fd use;
 allow dexoptanalyzer installd:fifo_file { getattr write };
 
diff --git a/private/domain.te b/private/domain.te
index e6b26f4..062a51e 100644
--- a/private/domain.te
+++ b/private/domain.te
@@ -271,6 +271,40 @@
   -otapreopt_slot
 } dalvikcache_data_file:dir no_w_dir_perms;
 
+# Only authorized processes should be writing to /data/misc/apexdata/com.android.art as it
+# contains boot class path and system server AOT artifacts following an ART APEX Mainline update.
+neverallow {
+  domain
+  # art processes
+  -odrefresh
+  # others
+  -apexd
+  -init
+  -vold_prepare_subdirs
+} apex_art_data_file:file no_w_file_perms;
+
+neverallow {
+  domain
+  # art processes
+  -odrefresh
+  # others
+  -apexd
+  -init
+  -vold_prepare_subdirs
+} apex_art_data_file:dir no_w_dir_perms;
+
+# Protect most domains from executing arbitrary content from /data.
+neverallow {
+  domain
+  -appdomain
+} {
+  data_file_type
+  -apex_art_data_file
+  -dalvikcache_data_file
+  -system_data_file # shared libs in apks
+  -apk_data_file
+}:file no_x_file_perms;
+
 # Minimize dac_override and dac_read_search.
 # Instead of granting them it is usually better to add the domain to
 # a Unix group or change the permissions of a file.
diff --git a/private/file.te b/private/file.te
index 993306b..cba2970 100644
--- a/private/file.te
+++ b/private/file.te
@@ -32,3 +32,9 @@
 
 # /data/misc/profcollectd
 type profcollectd_data_file, file_type, data_file_type, core_data_file_type;
+
+# /data/misc/apexdata/com.android.art
+type apex_art_data_file, file_type, data_file_type, core_data_file_type;
+
+# /data/misc/apexdata/com.android.art/staging
+type apex_art_staging_data_file, file_type, data_file_type, core_data_file_type;
diff --git a/private/file_contexts b/private/file_contexts
index 5330bdb..76d52c3 100644
--- a/private/file_contexts
+++ b/private/file_contexts
@@ -555,6 +555,7 @@
 # Misc data
 /data/misc/adb(/.*)?            u:object_r:adb_keys_file:s0
 /data/misc/apexdata(/.*)?       u:object_r:apex_module_data_file:s0
+/data/misc/apexdata/com\.android\.art(/.*)?    u:object_r:apex_art_data_file:s0
 /data/misc/apexdata/com\.android\.permission(/.*)?    u:object_r:apex_permission_data_file:s0
 /data/misc/apexdata/com\.android\.wifi(/.*)?    u:object_r:apex_wifi_data_file:s0
 /data/misc/apexrollback(/.*)?   u:object_r:apex_rollback_data_file:s0
diff --git a/private/heapprofd.te b/private/heapprofd.te
index 50039c2..d34830c 100644
--- a/private/heapprofd.te
+++ b/private/heapprofd.te
@@ -41,6 +41,7 @@
 # executables/libraries/etc to do stack unwinding.
 r_dir_file(heapprofd, nativetest_data_file)
 r_dir_file(heapprofd, system_file_type)
+r_dir_file(heapprofd, apex_art_data_file)
 r_dir_file(heapprofd, apk_data_file)
 r_dir_file(heapprofd, dalvikcache_data_file)
 r_dir_file(heapprofd, vendor_file_type)
diff --git a/private/incidentd.te b/private/incidentd.te
index 0731dec..eda55e3 100644
--- a/private/incidentd.te
+++ b/private/incidentd.te
@@ -136,6 +136,8 @@
 allow incidentd system_file:file lock;
 # Incidentd should never exec from the memory (e.g. JIT cache). These denials are expected.
 dontaudit incidentd dalvikcache_data_file:dir r_dir_perms;
+dontaudit incidentd apex_module_data_file:dir r_dir_perms;
+dontaudit incidentd apex_art_data_file:dir r_dir_perms;
 dontaudit incidentd tmpfs:file rwx_file_perms;
 
 # logd access - work to be done is a PII safe log (possibly an event log?)
diff --git a/private/iorap_inode2filename.te b/private/iorap_inode2filename.te
index 96b7bc2..5acb262 100644
--- a/private/iorap_inode2filename.te
+++ b/private/iorap_inode2filename.te
@@ -1,6 +1,8 @@
 typeattribute iorap_inode2filename coredomain;
 
 # Grant access to open most of the files under /
+allow iorap_inode2filename { apex_module_data_file apex_art_data_file }:dir r_dir_perms;
+allow iorap_inode2filename apex_data_file:file { getattr };
 allow iorap_inode2filename dalvikcache_data_file:dir { getattr open read search };
 allow iorap_inode2filename dalvikcache_data_file:file { getattr };
 allow iorap_inode2filename dex2oat_exec:lnk_file { getattr open read };
diff --git a/private/odrefresh.te b/private/odrefresh.te
new file mode 100644
index 0000000..c1ccc38
--- /dev/null
+++ b/private/odrefresh.te
@@ -0,0 +1,32 @@
+# odrefresh
+type odrefresh, domain, coredomain;
+type odrefresh_exec, system_file_type, exec_type, file_type;
+
+# Allow odrefresh to create files and directories for on device signing.
+allow odrefresh apex_module_data_file:dir { getattr search };
+allow odrefresh apex_art_data_file:dir { create_dir_perms relabelfrom };
+allow odrefresh apex_art_data_file:file { open create write read getattr unlink };
+
+# Staging area labels (/data/misc/apexdata/com.android.art/staging). odrefresh
+# sets up files here and passes file descriptors for dex2oat to write to.
+allow odrefresh apex_art_staging_data_file:dir { create_dir_perms relabelto };
+allow odrefresh apex_art_staging_data_file:file create_file_perms;
+
+# Run dex2oat in its own sandbox.
+domain_auto_trans(odrefresh, dex2oat_exec, dex2oat)
+
+# Run dexoptanalyzer in its own sandbox.
+domain_auto_trans(odrefresh, dexoptanalyzer_exec, dexoptanalyzer)
+
+# Do not audit unused resources from parent processes (adb, shell, su).
+# These appear to be unnecessary for odrefresh.
+dontaudit odrefresh { adbd shell }:fd use;
+dontaudit odrefresh devpts:chr_file rw_file_perms;
+dontaudit odrefresh adbd:unix_stream_socket { getattr read write };
+
+# Allow odrefresh to read /apex/apex-info-list.xml to determine
+# whether current apex is in /system or /data.
+allow odrefresh apex_info_file:file r_file_perms;
+
+# No other processes should be creating files in the staging area.
+neverallow { domain -init -odrefresh } apex_art_staging_data_file:file open;
diff --git a/private/su.te b/private/su.te
index 072e8db..587f449 100644
--- a/private/su.te
+++ b/private/su.te
@@ -13,6 +13,9 @@
   # Put the incident command into its domain so it is the same on user, userdebug and eng.
   domain_auto_trans(su, incident_exec, incident)
 
+  # Put the odrefresh command into its domain.
+  domain_auto_trans(su, odrefresh_exec, odrefresh)
+
   # Put the perfetto command into its domain so it is the same on user, userdebug and eng.
   domain_auto_trans(su, perfetto_exec, perfetto)
 
diff --git a/private/system_server.te b/private/system_server.te
index 12fb3fa..9f17021 100644
--- a/private/system_server.te
+++ b/private/system_server.te
@@ -32,8 +32,8 @@
 allowxperm system_server apk_data_file:file ioctl { INCFS_IOCTL_READ_SIGNATURE INCFS_IOCTL_FILL_BLOCKS INCFS_IOCTL_GET_FILLED_BLOCKS };
 
 # For art.
-allow system_server dalvikcache_data_file:dir r_dir_perms;
-allow system_server dalvikcache_data_file:file r_file_perms;
+allow system_server { apex_art_data_file dalvikcache_data_file }:dir r_dir_perms;
+allow system_server { apex_art_data_file dalvikcache_data_file }:file r_file_perms;
 
 # When running system server under --invoke-with, we'll try to load the boot image under the
 # system server domain, following links to the system partition.
diff --git a/private/traced_perf.te b/private/traced_perf.te
index 55d86fb..e5760f0 100644
--- a/private/traced_perf.te
+++ b/private/traced_perf.te
@@ -28,6 +28,7 @@
 # Allow reading files for stack unwinding and symbolization.
 r_dir_file(traced_perf, nativetest_data_file)
 r_dir_file(traced_perf, system_file_type)
+r_dir_file(traced_perf, apex_art_data_file)
 r_dir_file(traced_perf, apk_data_file)
 r_dir_file(traced_perf, dalvikcache_data_file)
 r_dir_file(traced_perf, vendor_file_type)
diff --git a/private/traced_probes.te b/private/traced_probes.te
index 9da4d94..d192bfd 100644
--- a/private/traced_probes.te
+++ b/private/traced_probes.te
@@ -48,6 +48,7 @@
 allow traced_probes self:global_capability_class_set dac_read_search;
 
 allow traced_probes apk_data_file:dir { getattr open read search };
+allow traced_probes { apex_art_data_file apex_module_data_file }:dir { getattr open read search };
 allow traced_probes dalvikcache_data_file:dir { getattr open read search };
 userdebug_or_eng(`
 # search and getattr are granted via domain and coredomain, respectively.
@@ -104,6 +105,8 @@
 # Disallows access to /data files.
 neverallow traced_probes {
   data_file_type
+  -apex_module_data_file
+  -apex_art_data_file
   -apk_data_file
   -dalvikcache_data_file
   -system_data_file
diff --git a/private/vold_prepare_subdirs.te b/private/vold_prepare_subdirs.te
index 9bea43c..b4e95b8 100644
--- a/private/vold_prepare_subdirs.te
+++ b/private/vold_prepare_subdirs.te
@@ -16,6 +16,7 @@
   vendor_data_file
 }:dir { open read write add_name remove_name rmdir relabelfrom };
 allow vold_prepare_subdirs {
+    apex_art_data_file
     apex_module_data_file
     apex_permission_data_file
     apex_rollback_data_file
@@ -30,6 +31,8 @@
     vold_data_file
 }:dir { create_dir_perms relabelto };
 allow vold_prepare_subdirs {
+    apex_art_data_file
+    apex_art_staging_data_file
     apex_module_data_file
     apex_permission_data_file
     apex_rollback_data_file
diff --git a/private/webview_zygote.te b/private/webview_zygote.te
index bdad219..bfdad06 100644
--- a/private/webview_zygote.te
+++ b/private/webview_zygote.te
@@ -28,9 +28,10 @@
 allow webview_zygote isolated_app:process dyntransition;
 
 # For art.
-allow webview_zygote dalvikcache_data_file:dir r_dir_perms;
+allow webview_zygote { apex_art_data_file dalvikcache_data_file }:dir r_dir_perms;
 allow webview_zygote dalvikcache_data_file:lnk_file r_file_perms;
-allow webview_zygote dalvikcache_data_file:file { r_file_perms execute };
+allow webview_zygote { apex_art_data_file dalvikcache_data_file }:file { r_file_perms execute };
+allow webview_zygote apex_module_data_file:dir search;
 
 # Allow webview_zygote to create JIT memory.
 allow webview_zygote self:process execmem;
diff --git a/private/zygote.te b/private/zygote.te
index 577ace8..23fed52 100644
--- a/private/zygote.te
+++ b/private/zygote.te
@@ -50,6 +50,13 @@
 # is ensured by fsverity protection (checked in art_apex_boot_integrity).
 allow zygote dalvikcache_data_file:file execute;
 
+# Allow zygote to find files in APEX data directories.
+allow zygote apex_module_data_file:dir search;
+
+# Allow zygote to find and map files created by on device signing.
+allow zygote apex_art_data_file:dir { getattr search };
+allow zygote apex_art_data_file:file { r_file_perms execute };
+
 # Bind mount on /data/data and mounted volumes
 allow zygote { system_data_file mnt_expand_file }:dir mounton;
 
@@ -225,9 +232,12 @@
   app_zygote
 }:process dyntransition;
 
-# Zygote should never execute anything from /data except for /data/dalvik-cache files.
+# Zygote should never execute anything from /data except for
+# /data/dalvik-cache files or files generated during on-device
+# signing under /data/misc/apexdata/com.android.art/.
 neverallow zygote {
   data_file_type
+  -apex_art_data_file # map PROT_EXEC
   -dalvikcache_data_file # map PROT_EXEC
 }:file no_x_file_perms;