microdroid: apk is mounted via apkdmverity

In microdroid, APK and its idsig is used to dm-verity mount before
zipfuse mounts it into a filesystem.

Bug: 190343842
Test: MicrodroidHostTestCases
Change-Id: Icd48fb823eabc087c0266e46f9b3d302e90fd208
diff --git a/microdroid/init.rc b/microdroid/init.rc
index 2385d8f..4155da3 100644
--- a/microdroid/init.rc
+++ b/microdroid/init.rc
@@ -22,6 +22,8 @@
 
     start ueventd
 
+    # TODO(b/190343842) verify apexes/apk before mounting them.
+
     # Exec apexd in the VM mode to avoid unnecessary overhead of normal mode.
     # (e.g. session management)
     exec - root system -- /system/bin/apexd --vm
@@ -29,6 +31,7 @@
     perform_apex_config
     exec_start derive_sdk
 
+    exec - root system -- /system/bin/apkdmverity /dev/block/by-name/microdroid-apk /dev/block/by-name/microdroid-apk-idsig microdroid-apk
     mkdir /mnt/apk 0755 system system
     start zipfuse
 
diff --git a/microdroid/sepolicy/system/private/apkdmverity.te b/microdroid/sepolicy/system/private/apkdmverity.te
new file mode 100644
index 0000000..c6160be
--- /dev/null
+++ b/microdroid/sepolicy/system/private/apkdmverity.te
@@ -0,0 +1,29 @@
+# apkdmverity is a program that protects a signed APK file using dm-verity.
+
+type apkdmverity, domain, coredomain;
+type apkdmverity_exec, exec_type, file_type, system_file_type;
+
+# allow domain transition from init
+init_daemon_domain(apkdmverity)
+
+# apkdmverity accesses /dev/block/by-name/metadata which points to
+# a /dev/vd* block device file.
+allow apkdmverity block_device:dir r_dir_perms;
+allow apkdmverity block_device:lnk_file r_file_perms;
+allow apkdmverity vd_device:blk_file r_file_perms;
+
+# allow apkdmverity to create dm-verity devices
+allow apkdmverity dm_device:{chr_file blk_file} rw_file_perms;
+# sys_admin is required to access the device-mapper and mount
+allow apkdmverity self:global_capability_class_set sys_admin;
+
+# allow apkdmverity to create loop devices with /dev/loop-control
+allow apkdmverity loop_control_device:chr_file rw_file_perms;
+
+# allow apkdmverity to access loop devices
+allow apkdmverity loop_device:blk_file rw_file_perms;
+allowxperm apkdmverity loop_device:blk_file ioctl {
+  LOOP_SET_STATUS64
+  LOOP_SET_FD
+  LOOP_SET_DIRECT_IO
+};
diff --git a/microdroid/sepolicy/system/private/domain.te b/microdroid/sepolicy/system/private/domain.te
index c451fcf..4a59f73 100644
--- a/microdroid/sepolicy/system/private/domain.te
+++ b/microdroid/sepolicy/system/private/domain.te
@@ -501,7 +501,8 @@
 
 # Only init and otapreopt_chroot should be mounting filesystems on locations
 # labeled system or vendor (/product and /vendor respectively).
-neverallow { domain -init -otapreopt_chroot } { system_file_type vendor_file_type }:dir_file_class_set mounton;
+# In microdroid, zipfuse is allowed mounton /mnt/apk.
+neverallow { domain -init -otapreopt_chroot -zipfuse } { system_file_type vendor_file_type }:dir_file_class_set mounton;
 
 # Only allow init and vendor_init to read/write mm_events properties
 # NOTE: dumpstate is allowed to read any system property
diff --git a/microdroid/sepolicy/system/private/file_contexts b/microdroid/sepolicy/system/private/file_contexts
index 3c75e81..5615e75 100644
--- a/microdroid/sepolicy/system/private/file_contexts
+++ b/microdroid/sepolicy/system/private/file_contexts
@@ -377,6 +377,7 @@
 /system/bin/zipfuse              u:object_r:zipfuse_exec:s0
 /system/bin/microdroid_launcher  u:object_r:microdroid_launcher_exec:s0
 /system/bin/microdroid_manager   u:object_r:microdroid_manager_exec:s0
+/system/bin/apkdmverity          u:object_r:apkdmverity_exec:s0
 
 #############################
 # Vendor files
diff --git a/microdroid/sepolicy/system/private/kernel.te b/microdroid/sepolicy/system/private/kernel.te
index cfec715..2d49445 100644
--- a/microdroid/sepolicy/system/private/kernel.te
+++ b/microdroid/sepolicy/system/private/kernel.te
@@ -32,3 +32,8 @@
 
 allow kernel kmsg_device:chr_file write;
 allow kernel gsid:fd use;
+
+# apkdmverity attaches a loop device to idsig file
+# and the loop device is used by zipfuse later.
+# This requires kernel to use the fd opened by apkdmverity.
+allow kernel apkdmverity:fd use;
diff --git a/microdroid/sepolicy/system/private/zipfuse.te b/microdroid/sepolicy/system/private/zipfuse.te
index 65da9d3..fb7527b 100644
--- a/microdroid/sepolicy/system/private/zipfuse.te
+++ b/microdroid/sepolicy/system/private/zipfuse.te
@@ -17,7 +17,9 @@
 # /dev/block/by-name/*
 allow zipfuse block_device:dir r_dir_perms;
 allow zipfuse block_device:lnk_file r_file_perms;
-allow zipfuse vd_device:blk_file r_file_perms;
+
+# /dev/block/by-name/microdroid-apk is mapped to /dev/block/dm-*
+allow zipfuse dm_device:blk_file r_file_perms;
 
 # allow mounting on /mnt/apk
 allow zipfuse tmpfs:dir mounton;