From 55d808c28c5291cb5f700e2b69cd642c6a687382 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 15 Dec 2022 13:38:42 +0000 Subject: [PATCH] Start using virtmgr for running VMs Split virtualizationservice policy into rules that should remain with the global service and rules that now apply to virtmgr - a child process of the client that runs the VM on its behalf. The virtualizationservice domain remains responsible for: * allocating CIDs (access to props) * creating temporary VM directories (virtualization_data_file, chown) * receiving tombstones from VMs * pushing atoms to statsd * removing memlock rlimit from virtmgr The new virtualizationmanager domain becomes responsible for: * executing crosvm * creating vsock connections, handling callbacks * preparing APEXes * pushing ramdumps to tombstoned * collecting stats for telemetry atoms The `virtualizationservice_use` macro is changed to allow client domains to transition to the virtmgr domain upon executing it as their child, and to allow communication over UDS. Clients are not allowed to communicate with virtualizationservice via Binder, only virtmgr is now allowed to do that. Bug: 250685929 Test: atest -p packages/modules/Virtualization:avf-presubmit Change-Id: Iefdccd908fc28e5d8c6f4566290e79ed88ade70b --- apex/com.android.virt-file_contexts | 2 +- private/app.te | 4 +- private/crosvm.te | 13 +++-- private/domain.te | 4 +- private/file.te | 8 +++- private/su.te | 3 ++ private/virtmgr.te | 8 ---- private/virtualizationmanager.te | 73 +++++++++++++++++++++++++++++ private/virtualizationservice.te | 73 +++++++++-------------------- public/te_macros | 37 ++++++--------- 10 files changed, 131 insertions(+), 94 deletions(-) delete mode 100644 private/virtmgr.te create mode 100644 private/virtualizationmanager.te diff --git a/apex/com.android.virt-file_contexts b/apex/com.android.virt-file_contexts index caef62d2d..9c13bd5cb 100644 --- a/apex/com.android.virt-file_contexts +++ b/apex/com.android.virt-file_contexts @@ -1,5 +1,5 @@ (/.*)? u:object_r:system_file:s0 /bin/crosvm u:object_r:crosvm_exec:s0 /bin/fd_server u:object_r:fd_server_exec:s0 -/bin/virtmgr u:object_r:virtmgr_exec:s0 +/bin/virtmgr u:object_r:virtualizationmanager_exec:s0 /bin/virtualizationservice u:object_r:virtualizationservice_exec:s0 diff --git a/private/app.te b/private/app.te index a7939b0d0..88387824b 100644 --- a/private/app.te +++ b/private/app.te @@ -95,9 +95,9 @@ neverallow appdomain system_server:udp_socket { # Exception for crash_dump to allow for app crash reporting. # Exception for renderscript binaries (/system/bin/bcc, /system/bin/ld.mc) # to allow renderscript to create privileged executable files. -# Exception for virtmgr to allow running VMs as child processes. +# Exception for virtualizationmanager to allow running VMs as child processes. neverallow { appdomain -shell userdebug_or_eng(`-su') } - { domain -appdomain -crash_dump -rs -virtmgr }:process { transition }; + { domain -appdomain -crash_dump -rs -virtualizationmanager }:process { transition }; neverallow { appdomain -shell userdebug_or_eng(`-su') } { domain -appdomain }:process { dyntransition }; diff --git a/private/crosvm.te b/private/crosvm.te index d4d29b0ec..c682bb504 100644 --- a/private/crosvm.te +++ b/private/crosvm.te @@ -14,10 +14,10 @@ neverallowxperm { domain -crosvm } kvm_device:chr_file ioctl ~{ KVM_CHECK_EXTENS tmpfs_domain(crosvm) # Let crosvm receive file descriptors from VirtualizationService. -allow crosvm virtualizationservice:fd use; +allow crosvm virtualizationmanager:fd use; # Allow sending VirtualizationService the failure reason from the VM via pipe. -allow crosvm virtualizationservice:fifo_file write; +allow crosvm virtualizationmanager:fifo_file write; # Let crosvm read the composite disk images (virtualizationservice_data_file), APEXes # (staging_data_file), APKs (apk_data_file and shell_data_file where the latter is for test apks in @@ -36,11 +36,14 @@ allow crosvm { # Allow searching the directory where the composite disk images are. allow crosvm virtualizationservice_data_file:dir search; +# Allow crosvm to mlock guest memory. +allow crosvm self:capability ipc_lock; + # Let crosvm access its control socket as created by VS. # read, write, getattr: listener socket polling # accept: listener socket accepting new connection # Note that the open permission is not given as the socket is passed by FD. -allow crosvm virtualizationservice:unix_stream_socket { accept read write getattr getopt }; +allow crosvm virtualizationmanager:unix_stream_socket { accept read write getattr getopt }; # Let crosvm open test artifacts under /data/local/tmp with file path. (e.g. custom pvmfw.img) userdebug_or_eng(` @@ -110,9 +113,9 @@ neverallow crosvm { -shell_data_file }:file read; -# Only virtualizationservice can run crosvm +# Only virtualizationmanager can run crosvm neverallow { domain -crosvm - -virtualizationservice + -virtualizationmanager } crosvm_exec:file no_x_file_perms; diff --git a/private/domain.te b/private/domain.te index 2b2619b9a..e0ba97554 100644 --- a/private/domain.te +++ b/private/domain.te @@ -290,7 +290,7 @@ neverallow { -apexd -installd -priv_app - -virtualizationservice + -virtualizationmanager } staging_data_file:dir *; neverallow { domain @@ -303,7 +303,7 @@ neverallow { -installd -priv_app -shell - -virtualizationservice + -virtualizationmanager -crosvm } staging_data_file:file *; neverallow { domain -init -system_server -installd} staging_data_file:dir no_w_dir_perms; diff --git a/private/file.te b/private/file.te index 134b37789..e33469fbd 100644 --- a/private/file.te +++ b/private/file.te @@ -91,7 +91,9 @@ type odsign_data_file, file_type, data_file_type, core_data_file_type; type odsign_metrics_file, file_type, data_file_type, core_data_file_type; # /data/misc/virtualizationservice -type virtualizationservice_data_file, file_type, data_file_type, core_data_file_type; +# The type needs to be mlstrustedobject to allow for being accessed from +# virtualizationmanager, which runs at a more constrained MLS level. +type virtualizationservice_data_file, file_type, data_file_type, core_data_file_type, mlstrustedobject; # /data/system/environ type environ_system_data_file, file_type, data_file_type, core_data_file_type; @@ -100,7 +102,9 @@ type environ_system_data_file, file_type, data_file_type, core_data_file_type; type bootanim_data_file, file_type, data_file_type, core_data_file_type; # /dev/kvm -type kvm_device, dev_type; +# The type needs to be mlstrustedobject to allow for being accessed from +# crosvm, which runs at a more constrained MLS level. +type kvm_device, dev_type, mlstrustedobject; # /apex/com.android.virt/bin/fd_server type fd_server_exec, system_file_type, exec_type, file_type; diff --git a/private/su.te b/private/su.te index 249647362..cc00e103b 100644 --- a/private/su.te +++ b/private/su.te @@ -19,6 +19,9 @@ userdebug_or_eng(` # Put the perfetto command into its domain so it is the same on user, userdebug and eng. domain_auto_trans(su, perfetto_exec, perfetto) + # Put the virtmgr command into its domain. + domain_auto_trans(su, virtualizationmanager_exec, virtualizationmanager) + # su is also permissive to permit setenforce. permissive su; diff --git a/private/virtmgr.te b/private/virtmgr.te deleted file mode 100644 index 225b6cbff..000000000 --- a/private/virtmgr.te +++ /dev/null @@ -1,8 +0,0 @@ -# Domain for a child process that manages virtual machines on behalf of its parent. - -type virtmgr, domain, coredomain; -type virtmgr_exec, system_file_type, exec_type, file_type; - -# Allow virtmgr to communicate use, read and write over the adb connection. -allow virtmgr adbd:fd use; -allow virtmgr adbd:unix_stream_socket { read write }; diff --git a/private/virtualizationmanager.te b/private/virtualizationmanager.te new file mode 100644 index 000000000..b27f36366 --- /dev/null +++ b/private/virtualizationmanager.te @@ -0,0 +1,73 @@ +# Domain for a child process that manages virtual machines on behalf of its parent. + +type virtualizationmanager, domain, coredomain; +type virtualizationmanager_exec, system_file_type, exec_type, file_type; + +# Allow virtualizationmanager to communicate use, read and write over the adb connection. +allow virtualizationmanager adbd:fd use; +allow virtualizationmanager adbd:unix_stream_socket { read write }; + +# Let the virtualizationmanager domain use Binder. +binder_use(virtualizationmanager) + +# Let virtualizationmanager find and communicate with virtualizationservice. +allow virtualizationmanager virtualization_service:service_manager find; +binder_call(virtualizationmanager, virtualizationservice) + +# Allow calling into the system server to find native services. "permission_service" to check +# permissions, and "package_native" for staged apex info. +binder_call(virtualizationmanager, system_server) +allow virtualizationmanager { package_native_service permission_service }:service_manager find; + +# When virtualizationmanager execs a file with the crosvm_exec label, run it in the crosvm domain. +domain_auto_trans(virtualizationmanager, crosvm_exec, crosvm) + +# Let virtualizationmanager kill crosvm. +allow virtualizationmanager crosvm:process sigkill; + +# Let virtualizationmanager create files inside virtualizationservice's temporary directories. +allow virtualizationmanager virtualizationservice_data_file:dir rw_dir_perms; +allow virtualizationmanager virtualizationservice_data_file:{ file sock_file } create_file_perms; + +# Let virtualizationmanager read and write files from its various clients, but not open them +# directly as they must be passed over Binder by the client. +allow virtualizationmanager apk_data_file:file { getattr read }; + +# Write access is needed for mutable partitions like instance.img +allow virtualizationmanager { + app_data_file + apex_compos_data_file + privapp_data_file +}:file { getattr read write }; + +# shell_data_file is used for automated tests and manual debugging. +allow virtualizationmanager shell_data_file:file { getattr read write }; + +# Allow virtualizationmanager to read apex-info-list.xml and access the APEX files listed there. +allow virtualizationmanager apex_info_file:file r_file_perms; +allow virtualizationmanager apex_data_file:dir search; +allow virtualizationmanager staging_data_file:file r_file_perms; +allow virtualizationmanager staging_data_file:dir search; + +# Run derive_classpath in our domain +allow virtualizationmanager derive_classpath_exec:file rx_file_perms; +allow virtualizationmanager apex_mnt_dir:dir r_dir_perms; +# Ignore harmless denials on /proc/self/fd +dontaudit virtualizationmanager self:dir write; + +# Let virtualizationmanager to accept vsock connection from the guest VMs +allow virtualizationmanager self:vsock_socket { create_socket_perms_no_ioctl listen accept }; + +# Allow virtualizationmanager to inspect all hypervisor capabilities. +get_prop(virtualizationmanager, hypervisor_prop) +get_prop(virtualizationmanager, hypervisor_restricted_prop) + +# Allow virtualizationmanager service to talk to tombstoned to push guest ramdumps +unix_socket_connect(virtualizationmanager, tombstoned_crash, tombstoned) + +# Append ramdumps to tombstone files passed as fds from tombstoned +allow virtualizationmanager tombstone_data_file:file { append getattr }; +allow virtualizationmanager tombstoned:fd use; + +# Allow reading files under /proc/[crosvm pid]/, for collecting CPU & memory usage inside VM. +r_dir_file(virtualizationmanager, crosvm); diff --git a/private/virtualizationservice.te b/private/virtualizationservice.te index 883ff563a..28982bc1d 100644 --- a/private/virtualizationservice.te +++ b/private/virtualizationservice.te @@ -1,80 +1,45 @@ type virtualizationservice, domain, coredomain; type virtualizationservice_exec, system_file_type, exec_type, file_type; +# The domain needs to be a 'mlstrustedsubject' to change the memlock rlimit of +# the virtualizationmanager domain running at a more constrained MLS level. +typeattribute virtualizationservice mlstrustedsubject; + # When init runs a file labelled with virtualizationservice_exec, run it in the # virtualizationservice domain. init_daemon_domain(virtualizationservice) # Let the virtualizationservice domain use Binder. binder_use(virtualizationservice) -# ... and host a binder service -binder_service(virtualizationservice) - -# Allow calling into the system server so that it can check permissions. -binder_call(virtualizationservice, system_server) -allow virtualizationservice permission_service:service_manager find; -# Allow virtualizationservice to access "package_native" service for staged apex info. -allow virtualizationservice package_native_service:service_manager find; # Let the virtualizationservice domain register the virtualization_service with ServiceManager. add_service(virtualizationservice, virtualization_service) -# When virtualizationservice execs a file with the crosvm_exec label, run it in the crosvm domain. -domain_auto_trans(virtualizationservice, crosvm_exec, crosvm) - -# Let virtualizationservice (and specifically its children) mlock VM memory and page tables. +# Let virtualizationservice remove memlock rlimit of virtualizationmanager. This is necessary +# to mlock VM memory and page tables. allow virtualizationservice self:capability sys_resource; +allow virtualizationservice virtualizationmanager:process setrlimit; -# Let virtualizationservice kill crosvm. -allow virtualizationservice crosvm:process sigkill; +# Let virtualizationservice set the owner of a VM's temporary directory. +allow virtualizationservice self:capability chown; -# Let virtualizationservice access its data directory. -allow virtualizationservice virtualizationservice_data_file:file create_file_perms; +# Let virtualizationservice create and delete temporary directories of VMs. To remove old +# directories, it needs the permission to unlink the files created by virtualizationmanager. allow virtualizationservice virtualizationservice_data_file:dir create_dir_perms; - -# Let virtualizationservice manage crosvm control sockets. -allow virtualizationservice virtualizationservice_data_file:sock_file create_file_perms; +allow virtualizationservice virtualizationservice_data_file:{ file sock_file } unlink; # Allow to use fd (e.g. /dev/pts/0) inherited from adbd so that we can redirect output from # crosvm to the console allow virtualizationservice adbd:fd use; allow virtualizationservice adbd:unix_stream_socket { read write }; -# Let virtualizationservice read and write files from its various clients, but not open them -# directly as they must be passed over Binder by the client. -allow virtualizationservice apk_data_file:file { getattr read }; -# Write access is needed for mutable partitions like instance.img -allow virtualizationservice { - app_data_file - apex_compos_data_file - privapp_data_file -}:file { getattr read write }; - -# shell_data_file is used for automated tests and manual debugging. -allow virtualizationservice shell_data_file:file { getattr read write }; - -# Allow virtualizationservice to read apex-info-list.xml and access the APEX files listed there. -allow virtualizationservice apex_info_file:file r_file_perms; -allow virtualizationservice apex_data_file:dir search; -allow virtualizationservice staging_data_file:file r_file_perms; -allow virtualizationservice staging_data_file:dir search; - -# Run derive_classpath in our domain -allow virtualizationservice derive_classpath_exec:file rx_file_perms; -allow virtualizationservice apex_mnt_dir:dir r_dir_perms; -# Ignore harmless denials on /proc/self/fd -dontaudit virtualizationservice self:dir write; - -# Let virtualizationservice to accept vsock connection from the guest VMs +# Let virtualizationservice to accept vsock connection from the guest VMs to singleton services +# such as the guest tombstone server. allow virtualizationservice self:vsock_socket { create_socket_perms_no_ioctl listen accept }; # Allow virtualizationservice to read/write its own sysprop. Only the process can do so. set_prop(virtualizationservice, virtualizationservice_prop) -# Allow virtualizationservice to inspect all hypervisor capabilities. -get_prop(virtualizationservice, hypervisor_prop) -get_prop(virtualizationservice, hypervisor_restricted_prop) - # Allow writing stats to statsd unix_socket_send(virtualizationservice, statsdw, statsd) @@ -85,9 +50,6 @@ unix_socket_connect(virtualizationservice, tombstoned_crash, tombstoned) allow virtualizationservice tombstone_data_file:file { append getattr }; allow virtualizationservice tombstoned:fd use; -# Allow reading files under /proc/[crosvm pid]/, for collecting CPU & memory usage inside VM. -r_dir_file(virtualizationservice, crosvm); - neverallow { domain -init @@ -97,5 +59,12 @@ neverallow { neverallow { domain -init + -virtualizationmanager -virtualizationservice } virtualizationservice_data_file:file { open create }; + +neverallow virtualizationservice { + domain + -virtualizationmanager + -virtualizationservice +}:process setrlimit; diff --git a/public/te_macros b/public/te_macros index 3bb390443..11041b643 100644 --- a/public/te_macros +++ b/public/te_macros @@ -183,32 +183,25 @@ neverallow $1 ~$1_userfaultfd:anon_inode *; #################################### # virtualizationservice_use(domain) # Allow domain to create and communicate with a virtual machine using -# virtualizationservice. +# virtualizationservice and virtualizationmanager. define(`virtualizationservice_use', ` -allow $1 virtualization_service:service_manager find; -# Let the client call virtualizationservice. -binder_call($1, virtualizationservice) -# Let virtualizationservice call back to the client. -binder_call(virtualizationservice, $1) -# Transition to virtmgr when the client executes it. -domain_auto_trans($1, virtmgr_exec, virtmgr) -# Allow virtmgr to communicate over UDS with the client. -allow virtmgr $1:unix_stream_socket { getattr read write }; -# Allow virtmgr and the client to signal each other using pipes. -allow virtmgr $1:fifo_file { getattr read write }; -# Let the client pass file descriptors to virtualizationservice/virtmgr and on -# to crosvm -allow { virtualizationservice virtmgr crosvm } $1:fd use; +# Transition to virtualizationmanager when the client executes it. +domain_auto_trans($1, virtualizationmanager_exec, virtualizationmanager) +# Allow virtualizationmanager to communicate over UDS with the client. +allow { virtualizationmanager crosvm } $1:unix_stream_socket { getattr read write }; +# Let the client pass file descriptors to virtualizationmanager and on to crosvm. +allow { virtualizationmanager crosvm } $1:fd use; +# Let the client use file descriptors created by virtualizationmanager. +allow $1 virtualizationmanager:fd use; # Allow piping console log to the client -allow { virtualizationservice crosvm } $1:fifo_file { getattr write}; -# Allow client to read/write vsock created by virtualizationservice to -# communicate with the VM that it created. Notice that we do not grant -# permission to create a vsock; the client can only connect to VMs -# that it owns. -allow $1 virtualizationservice:vsock_socket { getattr getopt read write }; +allow { virtualizationmanager crosvm } $1:fifo_file { getattr read write }; +# Allow client to read/write vsock created by virtualizationmanager to communicate with the VM +# that it created. Notice that we do not grant permission to create a vsock; +# the client can only connect to VMs that it owns. +allow $1 virtualizationmanager:vsock_socket { getattr getopt read write }; # Allow client to inspect hypervisor capabilities get_prop($1, hypervisor_prop) -# Allow client to read (but not open) the crashdump provided by virtualizationservice +# Allow client to read (but not open) the crashdump provided by virtualizationmanager allow $1 virtualizationservice_data_file:file { getattr read }; ')