mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
devices: fw_cfg: Don't modify kernel header for KVM SEV-SNP guests
For KVM SEV-SNP guests, the VMM should not modify the kernel boot header before sending it via fw_cfg. The guest firmware is expected to set fields like type_of_loader itself. For upcoming measured boot logic for SEV-SNP, modifying `type_of_loader` causes the kernel hash computed by the VMM to diverge from the hash that `sev-snp-measure` (and the guest firmware) compute, resulting in a launch measurement mismatch. This matches QEMU's behavior, which skips kernel header modifications for confidential guests so the data sent via fw_cfg matches the original kernel file provided by the user. Signed-off-by: Ruben Hakobyan <hruben@meta.com>
This commit is contained in:
committed by
Rob Bradford
parent
ffeee2880f
commit
9f1247fe60
@@ -441,12 +441,17 @@ impl FwCfg {
|
||||
initramfs: Option<File>,
|
||||
cmdline: Option<std::ffi::CString>,
|
||||
fw_cfg_item_list: Option<Vec<FwCfgItem>>,
|
||||
#[cfg(target_arch = "x86_64")] kvm_sev_snp_enabled: bool,
|
||||
) -> Result<()> {
|
||||
if let Some(mem_size) = mem_size {
|
||||
self.add_e820(mem_size)?;
|
||||
}
|
||||
if let Some(kernel) = kernel {
|
||||
self.add_kernel_data(&kernel)?;
|
||||
self.add_kernel_data(
|
||||
&kernel,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
kvm_sev_snp_enabled,
|
||||
)?;
|
||||
}
|
||||
if let Some(cmdline) = cmdline {
|
||||
self.add_kernel_cmdline(cmdline);
|
||||
@@ -631,24 +636,37 @@ impl FwCfg {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_kernel_data(&mut self, file: &File) -> Result<()> {
|
||||
pub fn add_kernel_data(
|
||||
&mut self,
|
||||
file: &File,
|
||||
#[cfg(target_arch = "x86_64")] kvm_sev_snp_enabled: bool,
|
||||
) -> Result<()> {
|
||||
let mut buffer = vec![0u8; size_of::<boot_params>()];
|
||||
file.read_exact_at(&mut buffer, 0)?;
|
||||
let bp = boot_params::from_mut_slice(&mut buffer).unwrap();
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
// must set to 4 for backwards compatibility
|
||||
// https://docs.kernel.org/arch/x86/boot.html#the-real-mode-kernel-header
|
||||
if bp.hdr.setup_sects == 0 {
|
||||
bp.hdr.setup_sects = 4;
|
||||
// For SEV-SNP guests on KVM, don't modify the kernel header so the
|
||||
// bytes sent via fw_cfg match what the VMM hashes for the launch digest.
|
||||
// The guest firmware handles these fields itself.
|
||||
if !kvm_sev_snp_enabled {
|
||||
if bp.hdr.setup_sects == 0 {
|
||||
bp.hdr.setup_sects = 4;
|
||||
}
|
||||
bp.hdr.type_of_loader = 0xff;
|
||||
}
|
||||
// wildcard boot loader type
|
||||
bp.hdr.type_of_loader = 0xff;
|
||||
}
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
let kernel_start = bp.text_offset;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let kernel_start = (bp.hdr.setup_sects as usize + 1) * 512;
|
||||
let kernel_start = {
|
||||
let sects = if bp.hdr.setup_sects == 0 {
|
||||
4
|
||||
} else {
|
||||
bp.hdr.setup_sects
|
||||
};
|
||||
(sects as usize + 1) * 512
|
||||
};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
if kernel_start <= buffer.len() {
|
||||
|
||||
@@ -1139,6 +1139,7 @@ impl Vm {
|
||||
fw_cfg_config: &FwCfgConfig,
|
||||
device_manager: &Arc<Mutex<DeviceManager>>,
|
||||
config: &Arc<Mutex<VmConfig>>,
|
||||
#[cfg(target_arch = "x86_64")] kvm_sev_snp_enabled: bool,
|
||||
) -> Result<()> {
|
||||
let mut e820_option: Option<usize> = None;
|
||||
if fw_cfg_config.e820 {
|
||||
@@ -1222,6 +1223,8 @@ impl Vm {
|
||||
initramfs_option,
|
||||
cmdline_option,
|
||||
fw_cfg_item_list_option,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
kvm_sev_snp_enabled,
|
||||
)
|
||||
.map_err(Error::ErrorPopulatingFwCfg)?;
|
||||
Ok(())
|
||||
@@ -2739,7 +2742,26 @@ impl Vm {
|
||||
.map(|p| p.fw_cfg_config.clone())
|
||||
.unwrap_or_default()
|
||||
.ok_or(Error::VmMissingConfig)?;
|
||||
Self::populate_fw_cfg(&fw_cfg_config, &self.device_manager, &self.config)?;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let kvm_sev_snp_enabled = {
|
||||
#[cfg(feature = "sev_snp")]
|
||||
{
|
||||
self.config.lock().unwrap().is_sev_snp_enabled()
|
||||
&& self.hypervisor.hypervisor_type() == hypervisor::HypervisorType::Kvm
|
||||
}
|
||||
#[cfg(not(feature = "sev_snp"))]
|
||||
{
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
Self::populate_fw_cfg(
|
||||
&fw_cfg_config,
|
||||
&self.device_manager,
|
||||
&self.config,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
kvm_sev_snp_enabled,
|
||||
)?;
|
||||
|
||||
if fw_cfg_config.acpi_tables {
|
||||
let tpm_enabled = self.config.lock().unwrap().tpm.is_some();
|
||||
|
||||
Reference in New Issue
Block a user