android_packages_modules_Vi.../microdroid/init.rc

211 lines
6.7 KiB
Plaintext
Raw Normal View History

# Copyright (C) 2021 The Android Open Source Project
#
# init.rc for microdroid. This contains a minimal script plus basic service definitions (e.g. apexd)
# needed for microdroid to run.
# TODO(b/179340780): support APEX init scripts
#
# IMPORTANT: Do not create world writable files or directories.
# This is a common source of Android security bugs.
#
import /init.environ.rc
# Cgroups are mounted right before early-init using list from /etc/cgroups.json
on early-init
# set RLIMIT_NICE to allow priorities from 19 to -20
setrlimit nice 40 40
start ueventd
APK roothash is trusted This CL completes the APK verification story in microdroid. Previously, the roothash of an APK that apkdmverity uses came from the idsig file. That file (and thus roothash in it) is untrusted because it's not signed by anyone. It is generated by virtualization service when the VM is created. With this CL, the roothash becomes trustful. Specifically, the roothash is from the instance disk which is encrypted and signed using the per-VM secret key. When the roothash in the instance disk is none, which could happen during the initial boot of the VM, we do the full APK verification (by scanning every bits), and save the roothash in the instance disk. In the subsequent boots, we skip the full APK verification, but instead compare the roothash with the saved one. If they differ, the boot is halted. 1) The start of apkdmverity and zipfuse is controlled by microdroid_manager. This is to NOT start them before the roothash is read from the instance disk. Previously, this was impossible because they are started by init while microdroid_manager is running in background. 2) apkdmverity now uses the bootstrap bionic libraries, because it is started far before APEXd activates APEXes. 3) microdroid_manager passes the roothash (read from instance disk) to apkdmverity via a new system property `microdroid_manager.apk_roothash`. This is preferred over to letting microdroid_manager directly execute apkdmverity and pass the roothash as a commandline argument. We don't want to allow microdroid_manager to fork/exec an executable other than app payload; there already is a selinux neverallow rule for it. 4) microdroid_manager waits for a new sysprop `linkerconfig.ready` to become `true` before it executes an app payload. Previously, this was implied because microdroid_manager waits for /mnt/apk which is created by zipfuse which in turn is executed after the linkerconfig is ready. Since zipfuse now is started much earlier, we no longer can rely on the implicit dependency. Bug: 193504400 Test: atest MicrodroidHostTestCases Test: run `adb shell /apex/com.android.virt/bin/vm run-app /data/local/tmp/virt/MicrodroidDemoApp.apk /data/local/tmp/virt/MicrodroidDemoApp.apk.idsig /data/local/tmp/virt/instance.img assets/vm_config.json` ... two times. In the first run: microdroid_manager[128]: payload verification successful. took 85.705852ms microdroid_manager[128]: Updating APK roothash: A4BC793C78E1A... In the second run: microdroid_manager[128]: payload verification successful. took 56.789795ms microdroid_manager[128]: Saved roothash is trustful. Not updating When the same command is invoked after the apk is intentionally modified, it fails as expected: init: Service 'microdroid_manager' (pid 128) exited with status 1 oneshot service took 0.202000 seconds in background Bug: 193504400 Change-Id: I469116d806cf3dae66fe41c04fdfd6bdb843edab
2021-09-06 06:59:21 +00:00
mkdir /mnt/apk 0755 system system
# Microdroid_manager starts apkdmverity/zipfuse/apexd
start microdroid_manager
# Wait for apexd to finish activating APEXes before starting more processes.
wait_for_prop apexd.status activated
perform_apex_config
APK roothash is trusted This CL completes the APK verification story in microdroid. Previously, the roothash of an APK that apkdmverity uses came from the idsig file. That file (and thus roothash in it) is untrusted because it's not signed by anyone. It is generated by virtualization service when the VM is created. With this CL, the roothash becomes trustful. Specifically, the roothash is from the instance disk which is encrypted and signed using the per-VM secret key. When the roothash in the instance disk is none, which could happen during the initial boot of the VM, we do the full APK verification (by scanning every bits), and save the roothash in the instance disk. In the subsequent boots, we skip the full APK verification, but instead compare the roothash with the saved one. If they differ, the boot is halted. 1) The start of apkdmverity and zipfuse is controlled by microdroid_manager. This is to NOT start them before the roothash is read from the instance disk. Previously, this was impossible because they are started by init while microdroid_manager is running in background. 2) apkdmverity now uses the bootstrap bionic libraries, because it is started far before APEXd activates APEXes. 3) microdroid_manager passes the roothash (read from instance disk) to apkdmverity via a new system property `microdroid_manager.apk_roothash`. This is preferred over to letting microdroid_manager directly execute apkdmverity and pass the roothash as a commandline argument. We don't want to allow microdroid_manager to fork/exec an executable other than app payload; there already is a selinux neverallow rule for it. 4) microdroid_manager waits for a new sysprop `linkerconfig.ready` to become `true` before it executes an app payload. Previously, this was implied because microdroid_manager waits for /mnt/apk which is created by zipfuse which in turn is executed after the linkerconfig is ready. Since zipfuse now is started much earlier, we no longer can rely on the implicit dependency. Bug: 193504400 Test: atest MicrodroidHostTestCases Test: run `adb shell /apex/com.android.virt/bin/vm run-app /data/local/tmp/virt/MicrodroidDemoApp.apk /data/local/tmp/virt/MicrodroidDemoApp.apk.idsig /data/local/tmp/virt/instance.img assets/vm_config.json` ... two times. In the first run: microdroid_manager[128]: payload verification successful. took 85.705852ms microdroid_manager[128]: Updating APK roothash: A4BC793C78E1A... In the second run: microdroid_manager[128]: payload verification successful. took 56.789795ms microdroid_manager[128]: Saved roothash is trustful. Not updating When the same command is invoked after the apk is intentionally modified, it fails as expected: init: Service 'microdroid_manager' (pid 128) exited with status 1 oneshot service took 0.202000 seconds in background Bug: 193504400 Change-Id: I469116d806cf3dae66fe41c04fdfd6bdb843edab
2021-09-06 06:59:21 +00:00
# Notify to microdroid_manager that perform_apex_config is done.
# Microdroid_manager shouldn't execute payload before this, because app
# payloads are not designed to run with bootstrap bionic
setprop apex_config.done true
setprop ro.debuggable ${ro.boot.microdroid.debuggable:-0}
on init
# Mount binderfs
mkdir /dev/binderfs
mount binder binder /dev/binderfs stats=global
chmod 0755 /dev/binderfs
symlink /dev/binderfs/binder /dev/binder
symlink /dev/binderfs/hwbinder /dev/hwbinder
symlink /dev/binderfs/vndbinder /dev/vndbinder
chmod 0666 /dev/binderfs/hwbinder
chmod 0666 /dev/binderfs/binder
chmod 0666 /dev/binderfs/vndbinder
# Prepare cpusets that are pre-defined by Android. Inside Microdroid, these however don't mean
# much because the mapping from vCPUs to physical CPUs are quite flexible; a VM can be started
# with any number of vCPUs and we in general can't be sure that vCPU N is a big core or a little
# core. These nodes are provided just to satisfy the code which puts a PID to a specific cpuset.
mkdir /dev/cpuset/foreground
copy /dev/cpuset/cpus /dev/cpuset/foreground/cpus
copy /dev/cpuset/mems /dev/cpuset/foreground/mems
mkdir /dev/cpuset/background
copy /dev/cpuset/cpus /dev/cpuset/background/cpus
copy /dev/cpuset/mems /dev/cpuset/background/mems
mkdir /dev/cpuset/system-background
copy /dev/cpuset/cpus /dev/cpuset/system-background/cpus
copy /dev/cpuset/mems /dev/cpuset/system-background/mems
chown system system /dev/cpuset
chown system system /dev/cpuset/foreground
chown system system /dev/cpuset/background
chown system system /dev/cpuset/system-background
chown system system /dev/cpuset/tasks
chown system system /dev/cpuset/foreground/tasks
chown system system /dev/cpuset/background/tasks
chown system system /dev/cpuset/system-background/tasks
chmod 0664 /dev/cpuset/tasks
chmod 0664 /dev/cpuset/foreground/tasks
chmod 0664 /dev/cpuset/background/tasks
chmod 0664 /dev/cpuset/system-background/tasks
on init && property:ro.boot.logd.enabled=1
# Start logd before any other services run to ensure we capture all of their logs.
start logd
on init
start servicemanager
# TODO(b/185767624): remove hidl after full keymint support
start hwservicemanager
on init && property:ro.boot.adb.enabled=1
start adbd
on load_persist_props_action && property:ro.boot.logd.enabled=1
start logd
start logd-reinit
# Mount filesystems and start core system services.
on late-init
trigger early-fs
# Mount fstab in init.{$device}.rc by mount_all command. Optional parameter
# '--early' can be specified to skip entries with 'latemount'.
# /system and /vendor must be mounted by the end of the fs stage,
# while /data is optional.
trigger fs
trigger post-fs
# Mount fstab in init.{$device}.rc by mount_all with '--late' parameter
# to only mount entries with 'latemount'. This is needed if '--early' is
# specified in the previous mount_all command on the fs stage.
# With /system mounted and properties form /system + /factory available,
# some services can be started.
trigger late-fs
trigger post-fs-data
# Load persist properties and override properties (if enabled) from /data.
trigger load_persist_props_action
trigger early-boot
trigger boot
on post-fs
# Once everything is setup, no need to modify /.
# The bind+remount combination allows this to work in containers.
mount rootfs rootfs / remount bind ro nodev
# TODO(b/185767624): change the hard-coded size?
mount tmpfs tmpfs /data noatime nosuid nodev rw size=128M
# We chown/chmod /data again so because mount is run as root + defaults
chown system system /data
chmod 0771 /data
# We restorecon /data in case the userdata partition has been reset.
restorecon /data
# set up keystore directory structure first so that we can end early boot
# and start apexd
mkdir /data/misc 01771 system misc
mkdir /data/misc/keystore 0700 keystore keystore
# work around b/183668221
restorecon /data/misc /data/misc/keystore
start keystore2
mkdir /data/misc/authfs 0700 root root
start authfs_service
on late-fs
start vendor.keymint-microdroid
on post-fs-data
mark_post_data
mkdir /data/vendor 0771 root root
mkdir /data/vendor_ce 0771 root root
mkdir /data/vendor_de 0771 root root
mkdir /data/vendor/hardware 0771 root root
# Start tombstoned early to be able to store tombstones.
# microdroid doesn't have anr, but tombstoned requires it
mkdir /data/anr 0775 system system
mkdir /data/tombstones 0771 system system
mkdir /data/vendor/tombstones 0771 root root
start tombstoned
# Boot level 30
# odsign signing keys have MAX_BOOT_LEVEL=30
# This is currently the earliest boot level, but we start at 30
# to leave room for earlier levels.
setprop keystore.boot_level 30
# For security reasons, /data/local/tmp should always be empty.
# Do not place files or directories in /data/local/tmp
mkdir /data/local 0751 root root
mkdir /data/local/tmp 0771 shell shell
service apexd-vm /system/bin/apexd --vm
user root
group system
oneshot
disabled
service ueventd /system/bin/ueventd
class core
critical
seclabel u:r:ueventd:s0
shutdown critical
service console /system/bin/sh
class core
console
disabled
user shell
group shell log readproc
seclabel u:r:shell:s0
setenv HOSTNAME console
service seriallogging /system/bin/logcat -b all -v threadtime -f /dev/hvc2 *:V
disabled
user logd
group root logd
on fs
write /dev/event-log-tags "# content owned by logd
"
chown logd logd /dev/event-log-tags
chmod 0644 /dev/event-log-tags
on property:sys.boot_completed=1
start logd-auditctl