From ee4c635de2a4c10957f1ccccc0414a4ffc288af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Wed, 24 Aug 2022 23:35:00 +0100 Subject: [PATCH] cmdline: Add --protected-vm-with-firmware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a mode where the VM is placed in protected mode but the protected firmware has been provided to crosvm and preloaded at its usual address, instead of being loaded by the hypervisor at VM boot time. This is useful for automated testing of firmware builds and development. BUG=b:243646855 TEST=build Change-Id: I849f3c6f0de55607893862d1d7739f6e1b410990 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3944853 Commit-Queue: Pierre-Clément Tosi Reviewed-by: Keiichi Watanabe Reviewed-by: Andrew Walbran Reviewed-by: Jiyong Park --- hypervisor/src/lib.rs | 13 +++++++++++-- src/crosvm/cmdline.rs | 12 ++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/hypervisor/src/lib.rs b/hypervisor/src/lib.rs index 9a29b74d4e..f007440f39 100644 --- a/hypervisor/src/lib.rs +++ b/hypervisor/src/lib.rs @@ -550,6 +550,9 @@ pub enum ProtectionType { /// The VM should be run in protected mode, so the host cannot access its memory directly. It /// should be booted via the protected VM firmware, so that it can access its secrets. Protected, + /// The VM should be run in protected mode, so the host cannot access its memory directly. It + /// should be booted via a custom VM firmware, useful for debugging and testing. + ProtectedWithCustomFirmware, /// The VM should be run in protected mode, but booted directly without pVM firmware. The host /// will still be unable to access the VM memory, but it won't be given any secrets. ProtectedWithoutFirmware, @@ -562,12 +565,18 @@ pub enum ProtectionType { impl ProtectionType { /// Returns whether the hypervisor will prevent us from accessing the VM's memory. pub fn isolates_memory(&self) -> bool { - matches!(self, Self::Protected | Self::ProtectedWithoutFirmware) + matches!( + self, + Self::Protected | Self::ProtectedWithCustomFirmware | Self::ProtectedWithoutFirmware + ) } /// Returns whether the VMM needs to load the pVM firmware. pub fn loads_firmware(&self) -> bool { - matches!(self, Self::UnprotectedWithFirmware) + matches!( + self, + Self::UnprotectedWithFirmware | Self::ProtectedWithCustomFirmware + ) } /// Returns whether the VM runs a pVM firmware. diff --git a/src/crosvm/cmdline.rs b/src/crosvm/cmdline.rs index 71e60a89d5..22635559ed 100644 --- a/src/crosvm/cmdline.rs +++ b/src/crosvm/cmdline.rs @@ -947,6 +947,9 @@ pub struct RunCommand { #[argh(switch)] /// prevent host access to guest memory pub protected_vm: bool, + #[argh(option, long = "protected-vm-with-firmware", arg_name = "PATH")] + /// (EXPERIMENTAL/FOR DEBUGGING) Use custom VM firmware to run in protected mode + pub protected_vm_with_firmware: Option, #[argh(switch)] /// (EXPERIMENTAL) prevent host access to guest memory, but don't use protected VM firmware protected_vm_without_firmware: bool, @@ -1782,6 +1785,7 @@ impl TryFrom for super::config::Config { let protection_flags = [ cmd.protected_vm, + cmd.protected_vm_with_firmware.is_some(), cmd.protected_vm_without_firmware, cmd.unprotected_vm_with_firmware.is_some(), ]; @@ -1794,6 +1798,14 @@ impl TryFrom for super::config::Config { ProtectionType::Protected } else if cmd.protected_vm_without_firmware { ProtectionType::ProtectedWithoutFirmware + } else if let Some(p) = cmd.protected_vm_with_firmware { + if !p.exists() || !p.is_file() { + return Err( + "protected-vm-with-firmware path should be an existing file".to_string() + ); + } + cfg.pvm_fw = Some(p); + ProtectionType::ProtectedWithCustomFirmware } else if let Some(p) = cmd.unprotected_vm_with_firmware { if !p.exists() || !p.is_file() { return Err(