runtime-rs: ch: Detect Intel TDX version

Improve the `GuestProtection` handling to detect the version of
Intel TDX available.

The TDX version is now logged by the Cloud Hypervisor driver.

Fixes: #8147.

Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>
This commit is contained in:
James O. D. Hunt
2023-10-05 17:53:07 +01:00
parent 538131ab44
commit 87b760f569
7 changed files with 229 additions and 43 deletions

View File

@@ -1574,6 +1574,7 @@ dependencies = [
"oci",
"once_cell",
"rand 0.8.5",
"safe-path 0.1.0",
"serde_json",
"slog",
"slog-scope",

View File

@@ -580,6 +580,7 @@ where
#[cfg(test)]
mod tests {
use super::*;
use kata_sys_util::protection::TDXDetails;
use kata_types::config::hypervisor::{
BlockDeviceInfo, Hypervisor as HypervisorConfig, SecurityInfo,
};
@@ -755,6 +756,11 @@ mod tests {
#[test]
fn test_get_serial_cfg() {
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
#[derive(Debug)]
struct TestData {
debug: bool,
@@ -783,7 +789,7 @@ mod tests {
},
TestData {
debug: false,
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: ConsoleConfig {
file: None,
mode: ConsoleOutputMode::Off,
@@ -792,7 +798,7 @@ mod tests {
},
TestData {
debug: true,
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: ConsoleConfig {
file: None,
mode: ConsoleOutputMode::Off,
@@ -838,6 +844,11 @@ mod tests {
#[test]
fn test_get_console_cfg() {
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
#[derive(Debug)]
struct TestData {
debug: bool,
@@ -866,7 +877,7 @@ mod tests {
},
TestData {
debug: false,
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: ConsoleConfig {
file: None,
mode: ConsoleOutputMode::Off,
@@ -875,7 +886,7 @@ mod tests {
},
TestData {
debug: true,
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: ConsoleConfig {
file: None,
mode: ConsoleOutputMode::Tty,
@@ -919,6 +930,11 @@ mod tests {
#[test]
fn test_get_platform_cfg() {
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
#[derive(Debug)]
struct TestData {
guest_protection: GuestProtection,
@@ -931,7 +947,7 @@ mod tests {
result: None,
},
TestData {
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: Some(PlatformConfig {
tdx: true,
num_pci_segments: DEFAULT_NUM_PCI_SEGMENTS,
@@ -1168,6 +1184,11 @@ mod tests {
#[test]
fn test_cpuinfo_to_cpusconfig() {
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
#[derive(Debug)]
struct TestData {
cpu_info: CpuInfo,
@@ -1258,7 +1279,7 @@ mod tests {
default_maxvcpus: 13,
..Default::default()
},
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: Ok(CpusConfig {
boot_vcpus: 1,
max_vcpus: 1,
@@ -1304,6 +1325,11 @@ mod tests {
#[test]
fn test_bootinfo_to_payloadconfig() {
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
#[derive(Debug)]
struct TestData {
boot_info: BootInfo,
@@ -1409,19 +1435,19 @@ mod tests {
..Default::default()
},
cmdline: None,
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: Err(PayloadConfigError::TDXFirmwareMissing),
},
TestData {
boot_info: boot_info_with_initrd,
cmdline: Some(cmdline.to_string()),
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: Ok(payload_config_with_initrd),
},
TestData {
boot_info: boot_info_without_initrd,
cmdline: Some(cmdline.to_string()),
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: Ok(payload_config_without_initrd),
},
];
@@ -1460,6 +1486,11 @@ mod tests {
#[test]
fn test_memoryinfo_to_memoryconfig() {
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
#[derive(Debug)]
struct TestData {
mem_info: MemoryInfo,
@@ -1494,7 +1525,7 @@ mod tests {
..Default::default()
},
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: Ok(MemoryConfig {
size: (17 * MIB),
shared: true,
@@ -1509,7 +1540,7 @@ mod tests {
..Default::default()
},
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: Ok(MemoryConfig {
size: usable_max_mem_bytes,
shared: true,
@@ -1524,7 +1555,7 @@ mod tests {
..Default::default()
},
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: Err(MemoryConfigError::DefaultMemSizeTooBig),
},
TestData {
@@ -1552,7 +1583,7 @@ mod tests {
},
TestData {
mem_info: mem_info_confidential_guest,
guest_protection: GuestProtection::Tdx,
guest_protection: GuestProtection::Tdx(tdx_details.clone()),
result: Ok(mem_cfg_confidential_guest),
},
];
@@ -1642,6 +1673,11 @@ mod tests {
#[test]
fn test_named_hypervisor_config_to_vmconfig() {
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
#[derive(Debug)]
struct TestData {
cfg: NamedHypervisorConfig,
@@ -1813,7 +1849,7 @@ mod tests {
..Default::default()
};
let platform_config_tdx = get_platform_cfg(GuestProtection::Tdx);
let platform_config_tdx = get_platform_cfg(GuestProtection::Tdx(tdx_details.clone()));
let vmconfig_tdx_image = VmConfig {
cpus: cpus_config_tdx.clone(),
@@ -1922,7 +1958,7 @@ mod tests {
vsock_socket_path: vsock_socket_path.into(),
cfg: hypervisor_cfg_tdx_image,
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
..Default::default()
};
@@ -1932,7 +1968,7 @@ mod tests {
vsock_socket_path: vsock_socket_path.into(),
cfg: hypervisor_cfg_tdx_initrd,
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
..Default::default()
};
@@ -2169,6 +2205,11 @@ mod tests {
#[test]
fn test_check_tdx_rootfs_settings() {
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
#[derive(Debug)]
struct TestData<'a> {
use_image: bool,
@@ -2220,7 +2261,7 @@ mod tests {
use_image: true,
container_rootfs_driver: "container",
vm_rootfs_driver: "vm",
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Err(VmConfigError::TDXContainerRootfsNotVirtioBlk),
},
// Partially correct
@@ -2228,28 +2269,28 @@ mod tests {
use_image: true,
container_rootfs_driver: VIRTIO_BLK_PCI,
vm_rootfs_driver: "vm",
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Err(VmConfigError::TDXVMRootfsNotVirtioBlk),
},
TestData {
use_image: true,
container_rootfs_driver: VIRTIO_BLK_MMIO,
vm_rootfs_driver: "vm",
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Err(VmConfigError::TDXVMRootfsNotVirtioBlk),
},
TestData {
use_image: true,
container_rootfs_driver: "container",
vm_rootfs_driver: VIRTIO_BLK_PCI,
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Err(VmConfigError::TDXContainerRootfsNotVirtioBlk),
},
TestData {
use_image: true,
container_rootfs_driver: "container",
vm_rootfs_driver: VIRTIO_BLK_MMIO,
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Err(VmConfigError::TDXContainerRootfsNotVirtioBlk),
},
// Same types
@@ -2257,14 +2298,14 @@ mod tests {
use_image: true,
container_rootfs_driver: VIRTIO_BLK_MMIO,
vm_rootfs_driver: VIRTIO_BLK_MMIO,
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Ok(()),
},
TestData {
use_image: true,
container_rootfs_driver: VIRTIO_BLK_PCI,
vm_rootfs_driver: VIRTIO_BLK_PCI,
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Ok(()),
},
// Alternate types
@@ -2272,14 +2313,14 @@ mod tests {
use_image: true,
container_rootfs_driver: VIRTIO_BLK_MMIO,
vm_rootfs_driver: VIRTIO_BLK_PCI,
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Ok(()),
},
TestData {
use_image: true,
container_rootfs_driver: VIRTIO_BLK_PCI,
vm_rootfs_driver: VIRTIO_BLK_MMIO,
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Ok(()),
},
// Using an initrd (not currently supported)
@@ -2287,28 +2328,28 @@ mod tests {
use_image: false,
container_rootfs_driver: VIRTIO_BLK_PCI,
vm_rootfs_driver: VIRTIO_BLK_PCI,
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Err(VmConfigError::TDXDisallowsInitrd),
},
TestData {
use_image: false,
container_rootfs_driver: "container",
vm_rootfs_driver: "vm",
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Err(VmConfigError::TDXDisallowsInitrd),
},
TestData {
use_image: false,
container_rootfs_driver: VIRTIO_BLK_PCI,
vm_rootfs_driver: "vm",
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Err(VmConfigError::TDXDisallowsInitrd),
},
TestData {
use_image: false,
container_rootfs_driver: VIRTIO_BLK_MMIO,
vm_rootfs_driver: "vm",
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
result: Err(VmConfigError::TDXDisallowsInitrd),
},
];

View File

@@ -504,15 +504,21 @@ pub struct NamedHypervisorConfig {
// Returns true if the enabled guest protection is Intel TDX.
pub fn guest_protection_is_tdx(guest_protection_to_use: GuestProtection) -> bool {
matches!(guest_protection_to_use, GuestProtection::Tdx)
matches!(guest_protection_to_use, GuestProtection::Tdx(_))
}
#[cfg(test)]
mod tests {
use super::*;
use kata_sys_util::protection::TDXDetails;
#[test]
fn test_guest_protection_is_tdx() {
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
#[derive(Debug)]
struct TestData {
protection: GuestProtection,
@@ -541,7 +547,7 @@ mod tests {
result: false,
},
TestData {
protection: GuestProtection::Tdx,
protection: GuestProtection::Tdx(tdx_details),
result: true,
},
];

View File

@@ -492,7 +492,7 @@ impl CloudHypervisorInner {
self.guest_protection_to_use = protection.clone();
info!(sl!(), "guest protection available and requested"; "guest-protection" => protection.to_string());
} else if protection == GuestProtection::Tdx {
} else if let GuestProtection::Tdx(_) = protection {
return Err(anyhow!(GuestProtectionError::TDXProtectionMustBeUsedWithCH));
} else {
info!(sl!(), "guest protection available but not requested"; "guest-protection" => protection.to_string());
@@ -724,6 +724,7 @@ fn get_guest_protection() -> Result<GuestProtection> {
#[cfg(test)]
mod tests {
use super::*;
use kata_sys_util::protection::TDXDetails;
#[cfg(target_arch = "x86_64")]
use kata_sys_util::protection::TDX_SYS_FIRMWARE_DIR;
@@ -748,6 +749,11 @@ mod tests {
// available_guest_protection() requires super user privs.
skip_if_not_root!();
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
#[derive(Debug)]
struct TestData {
value: Option<GuestProtection>,
@@ -776,8 +782,8 @@ mod tests {
result: Ok(GuestProtection::Snp),
},
TestData {
value: Some(GuestProtection::Tdx),
result: Ok(GuestProtection::Tdx),
value: Some(GuestProtection::Tdx(tdx_details.clone())),
result: Ok(GuestProtection::Tdx(tdx_details.clone())),
},
];
@@ -811,6 +817,11 @@ mod tests {
// available_guest_protection() requires super user privs.
skip_if_not_root!();
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
// Use the hosts protection, not a fake one.
set_fake_guest_protection(None);
@@ -843,7 +854,7 @@ mod tests {
}
if have_tdx {
assert_eq!(protection, GuestProtection::Tdx);
assert_eq!(protection, GuestProtection::Tdx(tdx_details));
} else {
assert_eq!(protection, GuestProtection::NoProtection);
}
@@ -866,6 +877,11 @@ mod tests {
guest_protection_to_use: GuestProtection,
}
let tdx_details = TDXDetails {
major_version: 1,
minor_version: 0,
};
let tests = &[
TestData {
confidential_guest: false,
@@ -881,15 +897,15 @@ mod tests {
},
TestData {
confidential_guest: false,
available_protection: Some(GuestProtection::Tdx),
available_protection: Some(GuestProtection::Tdx(tdx_details.clone())),
result: Err(anyhow!(GuestProtectionError::TDXProtectionMustBeUsedWithCH)),
guest_protection_to_use: GuestProtection::NoProtection,
},
TestData {
confidential_guest: true,
available_protection: Some(GuestProtection::Tdx),
available_protection: Some(GuestProtection::Tdx(tdx_details.clone())),
result: Ok(()),
guest_protection_to_use: GuestProtection::Tdx,
guest_protection_to_use: GuestProtection::Tdx(tdx_details.clone()),
},
];