mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-07-10 07:05:51 +00:00
kata-agent: Add dm-verity device cleanup for GPT-partitioned layers
Add per-container verity_devices tracking in Sandbox and wire the teardown path: destroy_partition_dmverity_device removes the device-mapper target via deferred-remove ioctl and deletes the mknod node, cleanup_dmverity_devices iterates all devices in reverse order. Wire into remove_container_resources (rpc.rs) so verity devices are torn down after unmount, and record verity device paths in add_storages (storage/mod.rs) for tracking. Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
This commit is contained in:
@@ -87,6 +87,7 @@ use crate::passfd_io;
|
||||
use crate::pci;
|
||||
use crate::random;
|
||||
use crate::sandbox::{Sandbox, SandboxError};
|
||||
use crate::storage::multi_layer_erofs::cleanup_dmverity_devices;
|
||||
use crate::storage::{add_storages, update_ephemeral_mounts, STORAGE_HANDLERS};
|
||||
use crate::util;
|
||||
use crate::version::{AGENT_VERSION, API_VERSION};
|
||||
@@ -2097,6 +2098,15 @@ async fn remove_container_resources(sandbox: &mut Sandbox, cid: &str) -> Result<
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup dm-verity devices for this container (after all mounts are unmounted)
|
||||
if let Some(verity_devices) = sandbox.container_verity_devices.remove(cid) {
|
||||
if !verity_devices.is_empty() {
|
||||
// Cleanup dm-verity devices for this container, ignoring any errors
|
||||
// since we want to proceed with cleanup as much as possible
|
||||
cleanup_dmverity_devices(&verity_devices, &sandbox.logger);
|
||||
}
|
||||
}
|
||||
|
||||
sandbox.container_mounts.remove(cid);
|
||||
sandbox.containers.remove(cid);
|
||||
// Remove any host -> guest mappings for this container
|
||||
|
||||
@@ -120,6 +120,8 @@ pub struct Sandbox {
|
||||
pub network: Network,
|
||||
pub mounts: Vec<String>,
|
||||
pub container_mounts: HashMap<String, Vec<String>>,
|
||||
/// dm-verity devices per container for cleanup
|
||||
pub container_verity_devices: HashMap<String, Vec<String>>,
|
||||
pub uevent_map: HashMap<String, Uevent>,
|
||||
pub uevent_watchers: Vec<Option<UeventWatcher>>,
|
||||
pub shared_utsns: Namespace,
|
||||
@@ -154,6 +156,7 @@ impl Sandbox {
|
||||
containers: HashMap::new(),
|
||||
mounts: Vec::new(),
|
||||
container_mounts: HashMap::new(),
|
||||
container_verity_devices: HashMap::new(),
|
||||
uevent_map: HashMap::new(),
|
||||
uevent_watchers: Vec::new(),
|
||||
shared_utsns: Namespace::new(&logger),
|
||||
|
||||
@@ -305,7 +305,20 @@ pub async fn add_storages(
|
||||
}
|
||||
}
|
||||
mount_list.extend(result.temp_mount_points);
|
||||
mount_list.extend(result.verity_devices);
|
||||
mount_list.extend(result.verity_devices.clone());
|
||||
|
||||
// Record verity devices for cleanup
|
||||
if let Some(ref cid) = cid {
|
||||
if !result.verity_devices.is_empty() {
|
||||
let mut sandbox_guard = sandbox.lock().await;
|
||||
sandbox_guard
|
||||
.container_verity_devices
|
||||
.entry(cid.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.extend(result.verity_devices.clone());
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -741,6 +741,62 @@ fn create_dmverity_device(verity_info: &DmVerityInfo, source_device_path: &Path)
|
||||
Ok(dev_path)
|
||||
}
|
||||
|
||||
/// Destroy a dm-verity device
|
||||
fn destroy_dmverity_device(verity_device_name: &str) -> Result<()> {
|
||||
let dm = devicemapper::DM::new()?;
|
||||
let name = devicemapper::DmName::new(verity_device_name)?;
|
||||
|
||||
dm.device_remove(&devicemapper::DevId::Name(name), dm_opts_deferred_remove())
|
||||
.context(format!("remove DmverityDevice {}", verity_device_name))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Destroy dm-verity device by path
|
||||
fn destroy_partition_dmverity_device(verity_device_path: &str, logger: &Logger) -> Result<()> {
|
||||
// The verity device path is /dev/mapper/<name> (as created by create_dm_dev_node).
|
||||
// Extract the DM device name for removal. Also remove the mknod-created device node.
|
||||
let device_name = verity_device_path
|
||||
.strip_prefix("/dev/mapper/")
|
||||
.unwrap_or(verity_device_path)
|
||||
.to_string();
|
||||
|
||||
destroy_dmverity_device(&device_name).context("Failed to destroy dm-verity device")?;
|
||||
info!(
|
||||
logger,
|
||||
"Destroying dm-verity device";
|
||||
"device-name" => &device_name,
|
||||
);
|
||||
|
||||
// Remove the device node we created with mknod.
|
||||
remove_dm_dev_node(verity_device_path);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Cleanup all dm-verity devices for a multi-layer EROFS mount
|
||||
pub fn cleanup_dmverity_devices(verity_devices: &[String], logger: &Logger) {
|
||||
info!(
|
||||
logger,
|
||||
"Cleaning up {} dm-verity devices",
|
||||
verity_devices.len()
|
||||
);
|
||||
|
||||
// Destroy in reverse order
|
||||
for verity_device in verity_devices.iter().rev() {
|
||||
if let Err(e) = destroy_partition_dmverity_device(verity_device, logger) {
|
||||
warn!(
|
||||
logger,
|
||||
"Failed to destroy dm-verity device";
|
||||
"device-path" => verity_device,
|
||||
"error" => format!("{:#}", e),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
info!(logger, "dm-verity device cleanup completed");
|
||||
}
|
||||
|
||||
/// Validate that a container ID does not contain path traversal sequences.
|
||||
///
|
||||
/// Container IDs are used to construct filesystem paths. A malicious ID containing
|
||||
|
||||
Reference in New Issue
Block a user