From 51e8310ef39b443f4aaa8b0bbdfece6c28fc8475 Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Tue, 26 May 2026 14:36:42 +0800 Subject: [PATCH] kata-agent: Integrate dm-verity into multi-layer EROFS mount path Wire the dm-verity helpers into the layer mount flow so that GPT partitions carrying verity metadata are mounted through a verified device-mapper target instead of the raw partition. Refactor wait_and_mount_layer to resolve partition path and verity device as separate steps: create a dm-verity device when X-kata.dmverity-enabled=true is set, fall back to direct partition mount otherwise, and return the verity device path for cleanup tracking. Signed-off-by: Alex Lyn --- src/agent/src/storage/multi_layer_erofs.rs | 48 ++++++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/src/agent/src/storage/multi_layer_erofs.rs b/src/agent/src/storage/multi_layer_erofs.rs index ca9c368568..19bb95641d 100644 --- a/src/agent/src/storage/multi_layer_erofs.rs +++ b/src/agent/src/storage/multi_layer_erofs.rs @@ -258,6 +258,7 @@ pub async fn handle_multi_layer_erofs_group( upper_storage = Some(*storage); } else if is_lower_storage(storage) { // Each GPT partition is provided as a separate storage entry by the host + // No special handling needed here - just add to erofs_storages if !has_gpt_partition && is_gpt_partitioned(storage) { has_gpt_partition = true; } @@ -532,6 +533,11 @@ fn is_lower_storage(storage: &Storage) -> bool { || (storage.fstype == EROFS_TYPE && storage.options.iter().any(|o| o == OPT_MULTI_LAYER)) } +/// Check if dm-verity is enabled for this storage +fn is_dmverity_enabled(storage: &Storage) -> bool { + storage.options.iter().any(|o| o == OPT_DMVERITY_ENABLED) +} + /// Parse dm-verity configuration from storage options fn parse_dmverity_options(storage: &Storage) -> Result { let mut hashtype = String::from("sha256"); @@ -921,21 +927,22 @@ async fn wait_and_mount_layer( let is_gpt = is_gpt_partitioned(layer); let partition_num = get_partition_number(layer); + let dmverity_enabled = is_dmverity_enabled(layer); // Get the base device path - let dev_path = match base_dev_path { + let base_dev_path = match base_dev_path { Some(path) => path, None => resolve_base_device_path(layer, sandbox).await?, }; // For GPT-partitioned disks, use the partition device path - let dev_path = if is_gpt { + let partition_path = if is_gpt { if let Some(part_num) = partition_num { - let path = get_partition_device_path(&dev_path, part_num); + let path = get_partition_device_path(&base_dev_path, part_num); info!( logger, "GPT-partitioned mode: using partition device"; - "base-device" => &dev_path, + "base-device" => &base_dev_path, "partition-number" => part_num, "partition-device" => &path, ); @@ -943,16 +950,41 @@ async fn wait_and_mount_layer( // Wait for partition device node to appear wait_for_partition_device(&path, logger).await?; - path + Some(path) } else { return Err(anyhow!( "GPT-partitioned storage missing partition number: {:?}", layer )); } + } else { + // Non-GPT mode: no partition path + None + }; + + // Determine the device path to mount + // If dm-verity is enabled, we'll create a verity device and mount that instead + let (dev_path, verity_device_path) = if dmverity_enabled { + // dm-verity mode: create verity device from partition + let partition = partition_path.as_ref().ok_or_else(|| { + anyhow!("dm-verity requires GPT-partitioned storage with partition number") + })?; + + // Create dm-verity device + let verity_device = create_partition_dmverity_device(partition, layer, logger)?; + info!( + logger, + "Using dm-verity device for mount"; + "partition" => partition, + "verity-device" => &verity_device, + ); + (verity_device.clone(), Some(verity_device)) + } else if let Some(ref partition) = partition_path { + // GPT mode without dm-verity: use partition directly + (partition.clone(), None) } else { // Non-GPT mode: use base device directly - dev_path.clone() + (base_dev_path.clone(), None) }; info!( @@ -963,6 +995,7 @@ async fn wait_and_mount_layer( "devname" => &dev_path, "mount-point" => layer_mount.display(), "gpt-mode" => is_gpt, + "dmverity-enabled" => dmverity_enabled, ); create_mount_destination(Path::new(&dev_path), layer_mount, "", &layer.fstype) @@ -1012,7 +1045,7 @@ async fn wait_and_mount_layer( track_temporary_mount_for_cleanup(sandbox, layer_mount, logger).await?; Ok(LayerMountInfo { - verity_device: None, + verity_device: verity_device_path, }) } @@ -1083,7 +1116,6 @@ fn get_partition_device_path(base_path: &str, partition_number: u32) -> String { /// When a virtio-blk device with a GPT is hotplugged, the kernel automatically /// scans the partition table and creates partition nodes. However, devtmpfs node /// creation may lag slightly behind the uevent, so we poll briefly if needed. -#[allow(dead_code)] async fn wait_for_partition_device(device_path: &str, logger: &Logger) -> Result<()> { let device_path_buf = PathBuf::from(device_path); if device_path_buf.exists() {