diff --git a/compos/common/compos_client.rs b/compos/common/compos_client.rs index 770f4896..946bc5b3 100644 --- a/compos/common/compos_client.rs +++ b/compos/common/compos_client.rs @@ -102,6 +102,7 @@ impl ComposClient { let config_path = parameters.config_path.as_deref().unwrap_or(DEFAULT_VM_CONFIG_PATH); let config = VirtualMachineConfig::AppConfig(VirtualMachineAppConfig { + name: String::from("Compos"), apk: Some(apk_fd), idsig: Some(idsig_fd), instanceImage: Some(instance_fd), diff --git a/javalib/src/android/system/virtualmachine/VirtualMachine.java b/javalib/src/android/system/virtualmachine/VirtualMachine.java index 955b3504..cc13ae5d 100644 --- a/javalib/src/android/system/virtualmachine/VirtualMachine.java +++ b/javalib/src/android/system/virtualmachine/VirtualMachine.java @@ -379,6 +379,7 @@ public class VirtualMachine { } VirtualMachineAppConfig appConfig = getConfig().toParcel(); + appConfig.name = mName; // Fill the idsig file by hashing the apk service.createOrUpdateIdsigFile( diff --git a/libs/vmconfig/src/lib.rs b/libs/vmconfig/src/lib.rs index 607b347d..7ca82725 100644 --- a/libs/vmconfig/src/lib.rs +++ b/libs/vmconfig/src/lib.rs @@ -33,6 +33,8 @@ use std::path::{Path, PathBuf}; /// Configuration for a particular VM to be started. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct VmConfig { + /// The name of VM. + pub name: Option, /// The filename of the kernel image, if any. pub kernel: Option, /// The filename of the initial ramdisk for the kernel, if any. @@ -91,6 +93,7 @@ impl VmConfig { } else { 0 }; + Ok(VirtualMachineRawConfig { kernel: maybe_open_parcel_file(&self.kernel, false)?, initrd: maybe_open_parcel_file(&self.initrd, false)?, diff --git a/rialto/tests/test.rs b/rialto/tests/test.rs index fb6a1ad5..8a78861e 100644 --- a/rialto/tests/test.rs +++ b/rialto/tests/test.rs @@ -54,6 +54,7 @@ fn test_boots() -> Result<(), Error> { let log = android_log_fd()?; let config = VirtualMachineConfig::RawConfig(VirtualMachineRawConfig { + name: String::from("RialtoTest"), kernel: None, initrd: None, params: None, diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl index 22b8a94f..8eb54974 100644 --- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl +++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl @@ -17,6 +17,9 @@ package android.system.virtualizationservice; /** Configuration for running an App in a VM */ parcelable VirtualMachineAppConfig { + /** Name of VM */ + String name; + /** Main APK */ ParcelFileDescriptor apk; diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl index 83a81a0a..d11de038 100644 --- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl +++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl @@ -19,6 +19,9 @@ import android.system.virtualizationservice.DiskImage; /** Raw configuration for running a VM. */ parcelable VirtualMachineRawConfig { + /** Name of VM */ + String name; + /** The kernel image, if any. */ @nullable ParcelFileDescriptor kernel; diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs index 10162d21..5f4b7a76 100644 --- a/virtualizationservice/src/aidl.rs +++ b/virtualizationservice/src/aidl.rs @@ -452,6 +452,7 @@ impl VirtualizationService { // Actually start the VM. let crosvm_config = CrosvmConfig { cid, + name: config.name.clone(), bootloader: maybe_clone_file(&config.bootloader)?, kernel: maybe_clone_file(&config.kernel)?, initrd: maybe_clone_file(&config.initrd)?, @@ -623,6 +624,7 @@ fn load_app_config( vm_config.memoryMib = config.memoryMib; } + vm_config.name = config.name.clone(); vm_config.protectedVm = config.protectedVm; vm_config.numCpus = config.numCpus; vm_config.cpuAffinity = config.cpuAffinity.clone(); @@ -1043,7 +1045,8 @@ impl IVirtualMachineService for VirtualMachineService { })?; let stream = vm.stream.lock().unwrap().take(); vm.callbacks.notify_payload_started(cid, stream); - write_vm_booted_stats(); + + write_vm_booted_stats(vm.requester_uid as i32, &vm.name); Ok(()) } else { error!("notifyPayloadStarted is called from an unknown CID {}", cid); diff --git a/virtualizationservice/src/atom.rs b/virtualizationservice/src/atom.rs index 7f1d6b17..feaa72ae 100644 --- a/virtualizationservice/src/atom.rs +++ b/virtualizationservice/src/atom.rs @@ -21,6 +21,7 @@ use android_system_virtualizationservice::aidl::android::system::virtualizations }; use android_system_virtualizationservice::binder::{Status, Strong}; use anyhow::{anyhow, Result}; +use binder::ThreadState; use log::{trace, warn}; use microdroid_payload_config::VmPayloadConfig; use statslog_virtualization_rust::{vm_booted, vm_creation_requested, vm_exited}; @@ -54,6 +55,7 @@ pub fn write_vm_creation_stats( } } + let vm_identifier; let config_type; let num_cpus; let cpu_affinity; @@ -61,6 +63,7 @@ pub fn write_vm_creation_stats( let apexes; match config { VirtualMachineConfig::AppConfig(config) => { + vm_identifier = &config.name; config_type = vm_creation_requested::ConfigType::VirtualMachineAppConfig; num_cpus = config.numCpus; cpu_affinity = config.cpuAffinity.clone().unwrap_or_default(); @@ -79,6 +82,7 @@ pub fn write_vm_creation_stats( } } VirtualMachineConfig::RawConfig(config) => { + vm_identifier = &config.name; config_type = vm_creation_requested::ConfigType::VirtualMachineRawConfig; num_cpus = config.numCpus; cpu_affinity = config.cpuAffinity.clone().unwrap_or_default(); @@ -87,11 +91,9 @@ pub fn write_vm_creation_stats( } } - let empty_string = String::new(); let vm_creation_requested = vm_creation_requested::VmCreationRequested { - // TODO(seungjaeyoo) Implement sending proper data about uid & vm_identifier - uid: -1, - vm_identifier: &empty_string, + uid: ThreadState::get_calling_uid() as i32, + vm_identifier, hypervisor: vm_creation_requested::Hypervisor::Pkvm, is_protected, creation_succeeded, @@ -114,13 +116,8 @@ pub fn write_vm_creation_stats( } /// Write the stats of VM boot to statsd -pub fn write_vm_booted_stats() { - let empty_string = String::new(); - let vm_booted = vm_booted::VmBooted { - // TODO(seungjaeyoo) Implement sending proper data about uid & vm_identifier - uid: -1, - vm_identifier: &empty_string, - }; +pub fn write_vm_booted_stats(uid: i32, vm_identifier: &String) { + let vm_booted = vm_booted::VmBooted { uid, vm_identifier }; match vm_booted.stats_write() { Err(e) => { warn!("statslog_rust failed with error: {}", e); @@ -130,12 +127,10 @@ pub fn write_vm_booted_stats() { } /// Write the stats of VM exit to statsd -pub fn write_vm_exited_stats(reason: DeathReason) { - let empty_string = String::new(); +pub fn write_vm_exited_stats(uid: i32, vm_identifier: &String, reason: DeathReason) { let vm_exited = vm_exited::VmExited { - // TODO(seungjaeyoo) Implement sending proper data about uid & vm_identifier - uid: -1, - vm_identifier: &empty_string, + uid, + vm_identifier, death_reason: match reason { DeathReason::INFRASTRUCTURE_ERROR => vm_exited::DeathReason::InfrastructureError, DeathReason::KILLED => vm_exited::DeathReason::Killed, diff --git a/virtualizationservice/src/crosvm.rs b/virtualizationservice/src/crosvm.rs index b4d173c9..aab78732 100644 --- a/virtualizationservice/src/crosvm.rs +++ b/virtualizationservice/src/crosvm.rs @@ -70,6 +70,7 @@ lazy_static! { #[derive(Debug)] pub struct CrosvmConfig { pub cid: Cid, + pub name: String, pub bootloader: Option, pub kernel: Option, pub initrd: Option, @@ -170,6 +171,8 @@ pub struct VmInstance { pub vm_state: Mutex, /// The CID assigned to the VM for vsock communication. pub cid: Cid, + /// The name of the VM. + pub name: String, /// Whether the VM is a protected VM. pub protected: bool, /// Directory of temporary files used by the VM while it is running. @@ -204,10 +207,12 @@ impl VmInstance { ) -> Result { validate_config(&config)?; let cid = config.cid; + let name = config.name.clone(); let protected = config.protected; Ok(VmInstance { vm_state: Mutex::new(VmState::NotStarted { config }), cid, + name, protected, temporary_directory, requester_uid, @@ -264,7 +269,7 @@ impl VmInstance { let death_reason = death_reason(&result, &failure_reason); self.callbacks.callback_on_died(self.cid, death_reason); - write_vm_exited_stats(death_reason); + write_vm_exited_stats(self.requester_uid as i32, &self.name, death_reason); // Delete temporary files. if let Err(e) = remove_dir_all(&self.temporary_directory) { diff --git a/vm/src/main.rs b/vm/src/main.rs index c421b045..ee0e2e6f 100644 --- a/vm/src/main.rs +++ b/vm/src/main.rs @@ -40,6 +40,10 @@ struct Idsigs(Vec); enum Opt { /// Run a virtual machine with a config in APK RunApp { + /// Name of VM + #[structopt(long)] + name: Option, + /// Path to VM Payload APK #[structopt(parse(from_os_str))] apk: PathBuf, @@ -102,6 +106,10 @@ enum Opt { }, /// Run a virtual machine Run { + /// Name of VM + #[structopt(long)] + name: Option, + /// Path to VM config JSON #[structopt(parse(from_os_str))] config: PathBuf, @@ -195,6 +203,7 @@ fn main() -> Result<(), Error> { match opt { Opt::RunApp { + name, apk, idsig, instance, @@ -211,6 +220,7 @@ fn main() -> Result<(), Error> { task_profiles, extra_idsigs, } => command_run_app( + name, service.as_ref(), &apk, &idsig, @@ -228,8 +238,9 @@ fn main() -> Result<(), Error> { task_profiles, &extra_idsigs, ), - Opt::Run { config, daemonize, cpus, cpu_affinity, task_profiles, console, log } => { + Opt::Run { name, config, daemonize, cpus, cpu_affinity, task_profiles, console, log } => { command_run( + name, service.as_ref(), &config, daemonize, diff --git a/vm/src/run.rs b/vm/src/run.rs index 9bd78630..05a93908 100644 --- a/vm/src/run.rs +++ b/vm/src/run.rs @@ -35,6 +35,7 @@ use zip::ZipArchive; /// Run a VM from the given APK, idsig, and config. #[allow(clippy::too_many_arguments)] pub fn command_run_app( + name: Option, service: &dyn IVirtualizationService, apk: &Path, idsig: &Path, @@ -91,6 +92,7 @@ pub fn command_run_app( let extra_idsig_fds = extra_idsig_files?.into_iter().map(ParcelFileDescriptor::new).collect(); let config = VirtualMachineConfig::AppConfig(VirtualMachineAppConfig { + name: name.unwrap_or_else(|| String::from("VmRunApp")), apk: apk_fd.into(), idsig: idsig_fd.into(), extraIdsigs: extra_idsig_fds, @@ -117,6 +119,7 @@ pub fn command_run_app( /// Run a VM from the given configuration file. #[allow(clippy::too_many_arguments)] pub fn command_run( + name: Option, service: &dyn IVirtualizationService, config_path: &Path, daemonize: bool, @@ -136,6 +139,11 @@ pub fn command_run( if let Some(cpus) = cpus { config.numCpus = cpus as i32; } + if let Some(name) = name { + config.name = name; + } else { + config.name = String::from("VmRun"); + } config.cpuAffinity = cpu_affinity; config.taskProfiles = task_profiles; run( diff --git a/vmbase/example/tests/test.rs b/vmbase/example/tests/test.rs index fd6eb8ca..58fffffd 100644 --- a/vmbase/example/tests/test.rs +++ b/vmbase/example/tests/test.rs @@ -48,7 +48,9 @@ fn test_run_example_vm() -> Result<(), Error> { File::open(VMBASE_EXAMPLE_PATH) .with_context(|| format!("Failed to open VM image {}", VMBASE_EXAMPLE_PATH))?, ); + let config = VirtualMachineConfig::RawConfig(VirtualMachineRawConfig { + name: String::from("VmBaseTest"), kernel: None, initrd: None, params: None,