vmm: pass host data to SevSnp guest

Host data that is passed to the hypervisor. Then
the firmware includes the data in the attestation report.
The data might include any key or secret that the SevSnp guest
might need later.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
This commit is contained in:
Muminul Islam 2024-02-08 11:53:56 -08:00 committed by Bo Chen
parent e51fb0ee36
commit 1a4c890f83
2 changed files with 43 additions and 8 deletions

View File

@ -53,6 +53,8 @@ pub enum Error {
ImportIsolatedPages(#[source] hypervisor::HypervisorVmError), ImportIsolatedPages(#[source] hypervisor::HypervisorVmError),
#[error("Error completing importing isolated pages: {0}")] #[error("Error completing importing isolated pages: {0}")]
CompleteIsolatedImport(#[source] hypervisor::HypervisorVmError), CompleteIsolatedImport(#[source] hypervisor::HypervisorVmError),
#[error("Error decoding host data: {0}")]
FailedToDecodeHostData(#[source] hex::FromHexError),
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -141,6 +143,7 @@ pub fn load_igvm(
memory_manager: Arc<Mutex<MemoryManager>>, memory_manager: Arc<Mutex<MemoryManager>>,
cpu_manager: Arc<Mutex<CpuManager>>, cpu_manager: Arc<Mutex<CpuManager>>,
cmdline: &str, cmdline: &str,
#[cfg(feature = "sev_snp")] host_data: &Option<String>,
) -> Result<Box<IgvmLoadedInfo>, Error> { ) -> Result<Box<IgvmLoadedInfo>, Error> {
let mut loaded_info: Box<IgvmLoadedInfo> = Box::default(); let mut loaded_info: Box<IgvmLoadedInfo> = Box::default();
let command_line = CString::new(cmdline).map_err(Error::InvalidCommandLine)?; let command_line = CString::new(cmdline).map_err(Error::InvalidCommandLine)?;
@ -149,6 +152,14 @@ pub fn load_igvm(
let mut gpas: Vec<GpaPages> = Vec::new(); let mut gpas: Vec<GpaPages> = Vec::new();
let proc_count = cpu_manager.lock().unwrap().vcpus().len() as u32; let proc_count = cpu_manager.lock().unwrap().vcpus().len() as u32;
#[cfg(feature = "sev_snp")]
let mut host_data_contents = [0; 32];
#[cfg(feature = "sev_snp")]
if let Some(host_data_str) = host_data {
hex::decode_to_slice(host_data_str, &mut host_data_contents as &mut [u8])
.map_err(Error::FailedToDecodeHostData)?;
}
file.seek(SeekFrom::Start(0)).map_err(Error::Igvm)?; file.seek(SeekFrom::Start(0)).map_err(Error::Igvm)?;
file.read_to_end(&mut file_contents).map_err(Error::Igvm)?; file.read_to_end(&mut file_contents).map_err(Error::Igvm)?;
@ -470,12 +481,11 @@ pub fn load_igvm(
now = Instant::now(); now = Instant::now();
// Call Complete Isolated Import since we are done importing isolated pages // Call Complete Isolated Import since we are done importing isolated pages
let host_data: [u8; 32] = [0; 32];
memory_manager memory_manager
.lock() .lock()
.unwrap() .unwrap()
.vm .vm
.complete_isolated_import(loaded_info.snp_id_block, host_data, 1) .complete_isolated_import(loaded_info.snp_id_block, host_data_contents, 1)
.map_err(Error::CompleteIsolatedImport)?; .map_err(Error::CompleteIsolatedImport)?;
info!( info!(

View File

@ -574,7 +574,13 @@ impl Vm {
// per cpuid through cpu_manager. // per cpuid through cpu_manager.
#[cfg(feature = "igvm")] #[cfg(feature = "igvm")]
let load_payload_handle = if snapshot.is_none() { let load_payload_handle = if snapshot.is_none() {
Self::load_payload_async(&memory_manager, &config, &cpu_manager)? Self::load_payload_async(
&memory_manager,
&config,
&cpu_manager,
#[cfg(feature = "sev_snp")]
sev_snp_enabled,
)?
} else { } else {
None None
}; };
@ -1006,8 +1012,16 @@ impl Vm {
igvm: File, igvm: File,
memory_manager: Arc<Mutex<MemoryManager>>, memory_manager: Arc<Mutex<MemoryManager>>,
cpu_manager: Arc<Mutex<cpu::CpuManager>>, cpu_manager: Arc<Mutex<cpu::CpuManager>>,
#[cfg(feature = "sev_snp")] host_data: &Option<String>,
) -> Result<EntryPoint> { ) -> Result<EntryPoint> {
let res = igvm_loader::load_igvm(&igvm, memory_manager, cpu_manager.clone(), "") let res = igvm_loader::load_igvm(
&igvm,
memory_manager,
cpu_manager.clone(),
"",
#[cfg(feature = "sev_snp")]
host_data,
)
.map_err(Error::IgvmLoad)?; .map_err(Error::IgvmLoad)?;
cfg_if::cfg_if! { cfg_if::cfg_if! {
@ -1087,13 +1101,21 @@ impl Vm {
payload: &PayloadConfig, payload: &PayloadConfig,
memory_manager: Arc<Mutex<MemoryManager>>, memory_manager: Arc<Mutex<MemoryManager>>,
#[cfg(feature = "igvm")] cpu_manager: Arc<Mutex<cpu::CpuManager>>, #[cfg(feature = "igvm")] cpu_manager: Arc<Mutex<cpu::CpuManager>>,
#[cfg(feature = "sev_snp")] sev_snp_enabled: bool,
) -> Result<EntryPoint> { ) -> Result<EntryPoint> {
trace_scoped!("load_payload"); trace_scoped!("load_payload");
#[cfg(feature = "igvm")] #[cfg(feature = "igvm")]
{
if let Some(_igvm_file) = &payload.igvm { if let Some(_igvm_file) = &payload.igvm {
let igvm = File::open(_igvm_file).map_err(Error::IgvmFile)?; let igvm = File::open(_igvm_file).map_err(Error::IgvmFile)?;
#[cfg(feature = "sev_snp")]
if sev_snp_enabled {
return Self::load_igvm(igvm, memory_manager, cpu_manager, &payload.host_data);
}
#[cfg(not(feature = "sev_snp"))]
return Self::load_igvm(igvm, memory_manager, cpu_manager); return Self::load_igvm(igvm, memory_manager, cpu_manager);
} }
}
match ( match (
&payload.firmware, &payload.firmware,
&payload.kernel, &payload.kernel,
@ -1135,6 +1157,7 @@ impl Vm {
memory_manager: &Arc<Mutex<MemoryManager>>, memory_manager: &Arc<Mutex<MemoryManager>>,
config: &Arc<Mutex<VmConfig>>, config: &Arc<Mutex<VmConfig>>,
#[cfg(feature = "igvm")] cpu_manager: &Arc<Mutex<cpu::CpuManager>>, #[cfg(feature = "igvm")] cpu_manager: &Arc<Mutex<cpu::CpuManager>>,
#[cfg(feature = "sev_snp")] sev_snp_enabled: bool,
) -> Result<Option<thread::JoinHandle<Result<EntryPoint>>>> { ) -> Result<Option<thread::JoinHandle<Result<EntryPoint>>>> {
// Kernel with TDX is loaded in a different manner // Kernel with TDX is loaded in a different manner
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
@ -1161,6 +1184,8 @@ impl Vm {
memory_manager, memory_manager,
#[cfg(feature = "igvm")] #[cfg(feature = "igvm")]
cpu_manager, cpu_manager,
#[cfg(feature = "sev_snp")]
sev_snp_enabled,
) )
}) })
.map_err(Error::KernelLoadThreadSpawn) .map_err(Error::KernelLoadThreadSpawn)