Add SELinux policy for using userfaultfd

ART runtime will be using userfaultfd for a new heap compaction
algorithm. After enabling userfaultfd in android kernels (with SELinux
support), the feature needs policy that allows { create ioctl read }
operations on userfaultfd file descriptors.

Bug: 160737021
Test: Manually tested by exercising userfaultfd ops in ART
Change-Id: I9ccb7fa9c25f91915639302715f6197d42ef988e
diff --git a/private/access_vectors b/private/access_vectors
index a02a2a8..7e5e7a5 100644
--- a/private/access_vectors
+++ b/private/access_vectors
@@ -182,6 +182,9 @@
 	entrypoint
 }
 
+class anon_inode
+inherits file
+
 class lnk_file
 inherits file
 
diff --git a/private/dex2oat.te b/private/dex2oat.te
index 909f94c..47ff77f 100644
--- a/private/dex2oat.te
+++ b/private/dex2oat.te
@@ -2,6 +2,8 @@
 type dex2oat, domain, coredomain;
 type dex2oat_exec, system_file_type, exec_type, file_type;
 
+userfaultfd_use(dex2oat)
+
 r_dir_file(dex2oat, apk_data_file)
 # Access to /vendor/app
 r_dir_file(dex2oat, vendor_app_file)
diff --git a/private/dexoptanalyzer.te b/private/dexoptanalyzer.te
index a99f8a2..5f0a41e 100644
--- a/private/dexoptanalyzer.te
+++ b/private/dexoptanalyzer.te
@@ -14,6 +14,8 @@
 # processes.
 tmpfs_domain(dexoptanalyzer)
 
+userfaultfd_use(dexoptanalyzer)
+
 # 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;
diff --git a/private/mls b/private/mls
index 1588a13..955c27b 100644
--- a/private/mls
+++ b/private/mls
@@ -48,6 +48,13 @@
 	     (l2 eq h2 and (l1 eq l2 or t1 == mlstrustedsubject));
 
 #
+# Userfaultfd constraints
+#
+# To enforce that anonymous inodes are self contained in the application's process.
+mlsconstrain anon_inode { ioctl read write create getattr setattr lock relabelfrom relabelto append map unlink link rename execute open execmod }
+	     (l1 eq l2);
+
+#
 # Constraints for app data files only.
 #
 
diff --git a/private/odrefresh.te b/private/odrefresh.te
index 9c615fa..e6b1023 100644
--- a/private/odrefresh.te
+++ b/private/odrefresh.te
@@ -7,6 +7,8 @@
 allow odrefresh apex_art_data_file:dir { create_dir_perms relabelfrom };
 allow odrefresh apex_art_data_file:file create_file_perms;
 
+userfaultfd_use(odrefresh)
+
 # 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 };
diff --git a/private/security_classes b/private/security_classes
index 3e9bff0..200b030 100644
--- a/private/security_classes
+++ b/private/security_classes
@@ -15,6 +15,7 @@
 # file-related classes
 class filesystem
 class file
+class anon_inode
 class dir
 class fd
 class lnk_file
diff --git a/private/system_server.te b/private/system_server.te
index 8bee1bf..9ef8363 100644
--- a/private/system_server.te
+++ b/private/system_server.te
@@ -12,6 +12,8 @@
 # Define a type for tmpfs-backed ashmem regions.
 tmpfs_domain(system_server)
 
+userfaultfd_use(system_server)
+
 # Create a socket for connections from crash_dump.
 type_transition system_server system_data_file:sock_file system_ndebug_socket "ndebugsocket";
 
diff --git a/private/webview_zygote.te b/private/webview_zygote.te
index bfdad06..3f217e1 100644
--- a/private/webview_zygote.te
+++ b/private/webview_zygote.te
@@ -10,6 +10,8 @@
 # a domain macro.
 tmpfs_domain(webview_zygote);
 
+userfaultfd_use(webview_zygote)
+
 # Allow reading/executing installed binaries to enable preloading the
 # installed WebView implementation.
 allow webview_zygote apk_data_file:dir r_dir_perms;
diff --git a/private/zygote.te b/private/zygote.te
index 83323c9..18babe0 100644
--- a/private/zygote.te
+++ b/private/zygote.te
@@ -24,6 +24,8 @@
 allow zygote appdomain:dir { getattr search };
 allow zygote appdomain:file { r_file_perms };
 
+userfaultfd_use(zygote)
+
 # Move children into the peer process group.
 allow zygote system_server:process { getpgid setpgid };
 allow zygote appdomain:process { getpgid setpgid };
diff --git a/public/te_macros b/public/te_macros
index 50532c1..1d919eb 100644
--- a/public/te_macros
+++ b/public/te_macros
@@ -163,6 +163,21 @@
 domain_auto_trans(init, $1_exec, $1)
 ')
 
+####################################
+# userfaultfd_use(domain)
+# Allow domain to create/use userfaultfd.
+define(`userfaultfd_use', `
+# Set up a type_transition to "userfaultfd" named anonymous inode object.
+type $1_userfaultfd;
+type_transition $1 $1:anon_inode $1_userfaultfd "[userfaultfd]";
+# Allow domain to create/use userfaultfd anon_inode.
+allow $1 $1_userfaultfd:anon_inode { create ioctl read };
+# Other domains may not use userfaultfd anon_inodes created by this domain.
+neverallow { domain -$1 } $1_userfaultfd:anon_inode *;
+# This domain may not use userfaultfd anon_inodes created by other domains.
+neverallow $1 ~$1_userfaultfd:anon_inode *;
+')
+
 #####################################
 # app_domain(domain)
 # Allow a base set of permissions required for all apps.
@@ -170,6 +185,7 @@
 typeattribute $1 appdomain;
 # Label tmpfs objects for all apps.
 type_transition $1 tmpfs:file appdomain_tmpfs;
+userfaultfd_use($1)
 allow $1 appdomain_tmpfs:file { execute getattr map read write };
 neverallow { $1 -runas_app -shell -simpleperf } { domain -$1 }:file no_rw_file_perms;
 neverallow { appdomain -runas_app -shell -simpleperf -$1 } $1:file no_rw_file_perms;