Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
f8cdc0d9ff build(deps): bump the tracing group across 4 directories with 1 update
Bumps the tracing group with 1 update in the /src/agent directory: [tracing](https://github.com/tokio-rs/tracing).
Bumps the tracing group with 1 update in the /src/tools/agent-ctl directory: [tracing](https://github.com/tokio-rs/tracing).
Bumps the tracing group with 1 update in the /src/tools/genpolicy directory: [tracing](https://github.com/tokio-rs/tracing).
Bumps the tracing group with 1 update in the /src/tools/kata-ctl directory: [tracing](https://github.com/tokio-rs/tracing).


Updates `tracing` from 0.1.41 to 0.1.44
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.41...tracing-0.1.44)

Updates `tracing` from 0.1.41 to 0.1.44
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.41...tracing-0.1.44)

Updates `tracing` from 0.1.41 to 0.1.44
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.41...tracing-0.1.44)

Updates `tracing` from 0.1.41 to 0.1.44
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.41...tracing-0.1.44)

---
updated-dependencies:
- dependency-name: tracing
  dependency-version: 0.1.44
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: tracing
- dependency-name: tracing
  dependency-version: 0.1.44
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: tracing
- dependency-name: tracing
  dependency-version: 0.1.44
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: tracing
- dependency-name: tracing
  dependency-version: 0.1.44
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: tracing
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-09 15:09:17 +00:00
21 changed files with 98 additions and 382 deletions

View File

@@ -184,7 +184,7 @@ thiserror = "1.0.26"
tokio = "1.46.1"
tokio-vsock = "0.3.4"
toml = "0.5.8"
tracing = "0.1.41"
tracing = "0.1.44"
tracing-opentelemetry = "0.18.0"
tracing-subscriber = "0.3.20"
ttrpc = "0.8.4"

View File

@@ -10,7 +10,7 @@ use std::sync::Arc;
use crate::storage::{common_storage_handler, new_device, StorageContext, StorageHandler};
use anyhow::{anyhow, Context, Result};
use kata_types::device::{DRIVER_OVERLAYFS_TYPE, DRIVER_VIRTIOFS_TYPE};
use kata_types::device::{DRIVER_9P_TYPE, DRIVER_OVERLAYFS_TYPE, DRIVER_VIRTIOFS_TYPE};
use kata_types::mount::{StorageDevice, KATA_VOLUME_OVERLAYFS_CREATE_DIR};
use protocols::agent::Storage;
use tracing::instrument;
@@ -69,6 +69,27 @@ impl StorageHandler for OverlayfsHandler {
}
}
#[derive(Debug)]
pub struct Virtio9pHandler {}
#[async_trait::async_trait]
impl StorageHandler for Virtio9pHandler {
#[instrument]
fn driver_types(&self) -> &[&str] {
&[DRIVER_9P_TYPE]
}
#[instrument]
async fn create_device(
&self,
storage: Storage,
ctx: &mut StorageContext,
) -> Result<Arc<dyn StorageDevice>> {
let path = common_storage_handler(ctx.logger, &storage)?;
new_device(path)
}
}
#[derive(Debug)]
pub struct VirtioFsHandler {}

View File

@@ -23,7 +23,7 @@ use tracing::instrument;
use self::bind_watcher_handler::BindWatcherHandler;
use self::block_handler::{PmemHandler, ScsiHandler, VirtioBlkMmioHandler, VirtioBlkPciHandler};
use self::ephemeral_handler::EphemeralHandler;
use self::fs_handler::{OverlayfsHandler, VirtioFsHandler};
use self::fs_handler::{OverlayfsHandler, Virtio9pHandler, VirtioFsHandler};
use self::image_pull_handler::ImagePullHandler;
use self::local_handler::LocalHandler;
use crate::mount::{baremount, is_mounted, remove_mounts};
@@ -134,6 +134,7 @@ lazy_static! {
pub static ref STORAGE_HANDLERS: StorageHandlerManager<Arc<dyn StorageHandler>> = {
let mut manager: StorageHandlerManager<Arc<dyn StorageHandler>> = StorageHandlerManager::new();
let handlers: Vec<Arc<dyn StorageHandler>> = vec![
Arc::new(Virtio9pHandler {}),
Arc::new(VirtioBlkMmioHandler {}),
Arc::new(VirtioBlkPciHandler {}),
Arc::new(EphemeralHandler {}),

View File

@@ -425,7 +425,7 @@ impl SandboxStorages {
/// or updated file to a target mount point, or remove the removed file from the target mount point. All WatchableStorage
/// target mount points are expected to reside within a single tmpfs, whose root is created by the BindWatcher.
///
/// This is a temporary workaround to handle config map updates until we get inotify on virtio-fs.
/// This is a temporary workaround to handle config map updates until we get inotify on 9p/virtio-fs.
/// More context on this:
/// - https://github.com/kata-containers/runtime/issues/1505
/// - https://github.com/kata-containers/kata-containers/issues/1879

View File

@@ -257,7 +257,7 @@ pub const KATA_ANNO_CFG_HYPERVISOR_ENABLE_ROOTLESS_HYPERVISOR: &str =
"io.katacontainers.config.hypervisor.rootless";
// Hypervisor Shared File System related annotations
/// A sandbox annotation to specify the shared file system type, either virtio-fs(default), inline-virtio-fs, virtio-fs-nydus or none.
/// A sandbox annotation to specify the shared file system type, either inline-virtio-fs (default), virtio-9p, virtio-fs or virtio-fs-nydus.
pub const KATA_ANNO_CFG_HYPERVISOR_SHARED_FS: &str =
"io.katacontainers.config.hypervisor.shared_fs";
/// A sandbox annotations to specify virtio-fs vhost-user daemon path.
@@ -272,6 +272,8 @@ pub const KATA_ANNO_CFG_HYPERVISOR_VIRTIO_FS_CACHE_SIZE: &str =
/// A sandbox annotation to pass options to virtiofsd daemon.
pub const KATA_ANNO_CFG_HYPERVISOR_VIRTIO_FS_EXTRA_ARGS: &str =
"io.katacontainers.config.hypervisor.virtio_fs_extra_args";
/// A sandbox annotation to specify as the msize for 9p shares.
pub const KATA_ANNO_CFG_HYPERVISOR_MSIZE_9P: &str = "io.katacontainers.config.hypervisor.msize_9p";
/// The initdata annotation passed in when CVM launchs
pub const KATA_ANNO_CFG_HYPERVISOR_INIT_DATA: &str =
"io.katacontainers.config.hypervisor.cc_init_data";
@@ -973,6 +975,14 @@ impl Annotation {
hv.shared_fs.virtio_fs_extra_args.push(arg.to_string());
}
}
KATA_ANNO_CFG_HYPERVISOR_MSIZE_9P => match self.get_value::<u32>(key) {
Ok(v) => {
hv.shared_fs.msize_9p = v.unwrap_or_default();
}
Err(_e) => {
return Err(u32_err);
}
},
KATA_ANNO_CFG_HYPERVISOR_BLOCK_DEV_NUM_QUEUES => {
match self.get_value::<usize>(key) {
Ok(v) => {

View File

@@ -47,6 +47,9 @@ pub const DEFAULT_BLOCK_DEVICE_QUEUE_SIZE: u32 = 128;
pub const DEFAULT_SHARED_FS_TYPE: &str = "virtio-fs";
pub const DEFAULT_VIRTIO_FS_CACHE_MODE: &str = "never";
pub const DEFAULT_VIRTIO_FS_DAX_SIZE_MB: u32 = 1024;
pub const DEFAULT_SHARED_9PFS_SIZE_MB: u32 = 8 * 1024;
pub const MIN_SHARED_9PFS_SIZE_MB: u32 = 4 * 1024;
pub const MAX_SHARED_9PFS_SIZE_MB: u32 = 8 * 1024 * 1024;
pub const DEFAULT_GUEST_HOOK_PATH: &str = "/opt/kata/hooks";
pub const DEFAULT_GUEST_DNS_FILE: &str = "/etc/resolv.conf";

View File

@@ -346,7 +346,7 @@ mod drop_in_directory_handling {
let dropin_override_data = r#"
[hypervisor.qemu]
shared_fs = "none"
shared_fs = "virtio-9p"
[runtime]
vfio_mode="vfio"
"#;
@@ -372,7 +372,7 @@ mod drop_in_directory_handling {
assert_eq!(config.hypervisor["qemu"].device_info.default_bridges, 4);
assert_eq!(
config.hypervisor["qemu"].shared_fs.shared_fs.as_deref(),
Some("none")
Some("virtio-9p")
);
assert!(config.runtime.debug);
assert!(config.runtime.sandbox_cgroup_only);

View File

@@ -68,6 +68,7 @@ mod firecracker;
pub use self::firecracker::{FirecrackerConfig, HYPERVISOR_NAME_FIRECRACKER};
const NO_VIRTIO_FS: &str = "none";
const VIRTIO_9P: &str = "virtio-9p";
const VIRTIO_FS: &str = "virtio-fs";
const VIRTIO_FS_INLINE: &str = "inline-virtio-fs";
const MAX_BRIDGE_SIZE: u32 = 5;
@@ -1418,13 +1419,12 @@ impl SecurityInfo {
}
}
/// Configuration information for shared filesystems, such as virtio-fs-nydus and virtio-fs.
/// Configuration information for shared filesystems, such as virtio-9p and virtio-fs.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct SharedFsInfo {
/// Type of shared file system to use:
/// - `virtio-fs` (default)
/// - `inline-virtio-fs`
/// - `virtio-fs-nydus`
/// - `virtio-9p`
/// - `none` (disables shared filesystem)
pub shared_fs: Option<String>,
@@ -1466,13 +1466,18 @@ pub struct SharedFsInfo {
/// Enables `virtio-fs` DAX (Direct Access) window if `true`.
#[serde(default)]
pub virtio_fs_is_dax: bool,
/// This is the `msize` used for 9p shares. It represents the number of bytes
/// used for the 9p packet payload.
#[serde(default)]
pub msize_9p: u32,
}
impl SharedFsInfo {
/// Adjusts the shared filesystem configuration after loading from a configuration file.
///
/// Handles default values for `shared_fs` type, `virtio-fs` specific settings
/// (daemon path, cache mode, DAX) or `inline-virtio-fs` settings.
/// (daemon path, cache mode, DAX), and `virtio-9p` msize.
pub fn adjust_config(&mut self) -> Result<()> {
if self.shared_fs.as_deref() == Some(NO_VIRTIO_FS) {
self.shared_fs = None;
@@ -1485,6 +1490,11 @@ impl SharedFsInfo {
match self.shared_fs.as_deref() {
Some(VIRTIO_FS) => self.adjust_virtio_fs(false)?,
Some(VIRTIO_FS_INLINE) => self.adjust_virtio_fs(true)?,
Some(VIRTIO_9P) => {
if self.msize_9p == 0 {
self.msize_9p = default::DEFAULT_SHARED_9PFS_SIZE_MB;
}
}
_ => {}
}
@@ -1494,12 +1504,23 @@ impl SharedFsInfo {
/// Validates the shared filesystem configuration.
///
/// Checks the validity of the selected `shared_fs` type and
/// performs specific validations for `virtio-fs` and `inline-virtio-fs` settings.
/// performs specific validations for `virtio-fs` and `virtio-9p` settings.
pub fn validate(&self) -> Result<()> {
match self.shared_fs.as_deref() {
None => Ok(()),
Some(VIRTIO_FS) => self.validate_virtio_fs(false),
Some(VIRTIO_FS_INLINE) => self.validate_virtio_fs(true),
Some(VIRTIO_9P) => {
if self.msize_9p < default::MIN_SHARED_9PFS_SIZE_MB
|| self.msize_9p > default::MAX_SHARED_9PFS_SIZE_MB
{
return Err(std::io::Error::other(format!(
"Invalid 9p configuration msize 0x{:x}, min value is 0x{:x}, max value is 0x{:x}",
self.msize_9p,default::MIN_SHARED_9PFS_SIZE_MB, default::MAX_SHARED_9PFS_SIZE_MB
)));
}
Ok(())
}
Some(v) => Err(std::io::Error::other(format!("Invalid shared_fs type {v}"))),
}
}

View File

@@ -27,6 +27,8 @@ pub const DRIVER_VFIO_AP_TYPE: &str = "vfio-ap";
/// DRIVER_VFIO_AP_COLD_TYPE is the device driver for vfio-ap coldplug.
pub const DRIVER_VFIO_AP_COLD_TYPE: &str = "vfio-ap-cold";
/// DRIVER_9P_TYPE is the driver for 9pfs volume.
pub const DRIVER_9P_TYPE: &str = "9p";
/// DRIVER_EPHEMERAL_TYPE is the driver for ephemeral volume.
pub const DRIVER_EPHEMERAL_TYPE: &str = "ephemeral";
/// DRIVER_LOCAL_TYPE is the driver for local volume.

View File

@@ -48,6 +48,7 @@ file_mem_backend = "/dev/shm"
valid_file_mem_backends = ["/dev/shm","/dev/snd","./test_file_backend_mem_root"]
pflashes = ["/proc/mounts"]
enable_debug = true
msize_9p = 16384
disable_image_nvdimm = true
hotplug_vfio_on_root_bus = true
pcie_root_port = 2

View File

@@ -47,6 +47,7 @@ file_mem_backend = "/dev/shm"
valid_file_mem_backends = ["/dev/shm"]
pflashes = ["/proc/mounts"]
enable_debug = true
msize_9p = 16384
disable_image_nvdimm = true
hotplug_vfio_on_root_bus = true
pcie_root_port = 2

View File

@@ -493,7 +493,7 @@ message SharedMount {
// could have been defined through the Mount list of the OCI specification.
message Storage {
// Driver is used to define the way the storage is passed through the
// virtual machine. It can be "blk", or something else, but for
// virtual machine. It can be "9p", "blk", or something else, but for
// all cases, this will define if some extra steps are required before
// this storage gets mounted into the container.
string driver = 1;
@@ -509,7 +509,7 @@ message Storage {
string source = 3;
// Fstype represents the filesystem that needs to be used to mount the
// storage inside the VM. For instance, it could be "xfs" for block
// device, or "tmpfs" for shared /dev/shm.
// device, "9p" for shared filesystem, or "tmpfs" for shared /dev/shm.
string fstype = 4;
// Options describes the additional options that might be needed to
// mount properly the storage filesystem.

View File

@@ -174,6 +174,7 @@ guest_hook_path = ""
# Shared file system type:
# - inline-virtio-fs (default)
# - virtio-fs
# - virtio-9p
# - virtio-fs-nydus
# "inline-virtio-fs" is the same as "virtio-fs", but it is running in the same process
# of shim, does not need an external virtiofsd process.

View File

@@ -179,6 +179,7 @@ disable_block_device_use = @DEFDISABLEBLOCK@
# Shared file system type:
# - virtio-fs (default)
# - virtio-9p
# - virtio-fs-nydus
# - none
shared_fs = "@DEFSHAREDFS_QEMU_COCO_DEV_VIRTIOFS@"

View File

@@ -163,6 +163,7 @@ disable_block_device_use = @DEFDISABLEBLOCK@
# Shared file system type:
# - virtio-fs (default)
# - virtio-9p
# - virtio-fs-nydus
# - none
shared_fs = "@DEFSHAREDFS_QEMU_VIRTIOFS@"

View File

@@ -162,6 +162,7 @@ disable_block_device_use = @DEFDISABLEBLOCK@
# Shared file system type:
# - virtio-fs (default)
# - virtio-9p
# - virtio-fs-nydus
# - none
shared_fs = "@DEFSHAREDFS_QEMU_SEL_VIRTIOFS@"

View File

@@ -1519,8 +1519,6 @@ CopyFileRequest if {
check_directory_traversal(input.path)
allow_copy_file(input.path, input.file_mode, input.data)
some regex1 in policy_data.request_defaults.CopyFileRequest
regex2 := replace(regex1, "$(sfprefix)", policy_data.common.sfprefix)
regex3 := replace(regex2, "$(cpath)", policy_data.common.cpath)
@@ -1532,39 +1530,6 @@ CopyFileRequest if {
print("CopyFileRequest: true")
}
allow_copy_file(path, mode, data) if {
print("allow_copy_file regular")
bits.and(mode, 61440) == 32768
print("allow_copy_file regular: true")
}
allow_copy_file(path, mode, data) if {
print("allow_copy_file dir")
bits.and(mode, 61440) == 16384
print("allow_copy_file dir: true")
}
allow_copy_file(path, mode, data) if {
print("allow_copy_file symlink")
bits.and(mode, 61440) == 40960
target := concat("", [sprintf("%c", [c]) | c := data[_]])
check_directory_traversal(target)
not startswith(target, "/")
regex1 := concat("", [policy_data.common.sfprefix, ".*/.+"])
regex2 := replace(regex1, "$(cpath)", policy_data.common.cpath)
regex3 := replace(regex2, "$(bundle-id)", "[a-z0-9]{64}")
regex.match(regex3, path)
print("allow_copy_file symlink: true")
}
CreateSandboxRequest if {
print("CreateSandboxRequest: input.guest_hook_path =", input.guest_hook_path)
count(input.guest_hook_path) == 0

View File

@@ -4,7 +4,6 @@
"description": "copy initiated by k8s mount",
"kind": "CopyFileRequest",
"request": {
"file_mode": 33206,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-resolv.conf"
}
},
@@ -13,7 +12,6 @@
"description": "a dirname can have trailing dots",
"kind": "CopyFileRequest",
"request": {
"file_mode": 33206,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo../bar"
}
},
@@ -22,7 +20,6 @@
"description": "attempt to copy outside of container root",
"kind": "CopyFileRequest",
"request": {
"file_mode": 33206,
"path": "/etc/ssl/cert.pem"
}
},
@@ -31,7 +28,6 @@
"description": "attempt to write into container root",
"kind": "CopyFileRequest",
"request": {
"file_mode": 33206,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc/rootfs/bin/sh"
}
},
@@ -40,7 +36,6 @@
"description": "attempt to write into container root - guest pull",
"kind": "CopyFileRequest",
"request": {
"file_mode": 33206,
"path": "/run/kata-containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc/rootfs/bin/sh"
}
},
@@ -49,7 +44,6 @@
"description": "attempted directory traversal",
"kind": "CopyFileRequest",
"request": {
"file_mode": 33206,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/../../../../../etc/ssl/cert.pem"
}
},
@@ -58,7 +52,6 @@
"description": "attempted directory traversal - parent directory",
"kind": "CopyFileRequest",
"request": {
"file_mode": 16895,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/.."
}
},
@@ -67,7 +60,6 @@
"description": "relative path",
"kind": "CopyFileRequest",
"request": {
"file_mode": 33206,
"path": "etc/ssl/cert.pem"
}
},
@@ -76,122 +68,7 @@
"description": "relative path - parent directory",
"kind": "CopyFileRequest",
"request": {
"file_mode": 16895,
"path": ".."
}
},
{
"allowed": false,
"description": "unsupported S_IFBLK",
"kind": "CopyFileRequest",
"request": {
"file_mode": 24576,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/bar"
}
},
{
"allowed": false,
"description": "unsupported S_IFSOCK",
"kind": "CopyFileRequest",
"request": {
"file_mode": 49152,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/bar"
}
},
{
"allowed": false,
"description": "unsupported S_IFIFO",
"kind": "CopyFileRequest",
"request": {
"file_mode": 4096,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/bar"
}
},
{
"allowed": false,
"description": "unsupported mixed mode (S_IFREG | S_IFLNK)",
"kind": "CopyFileRequest",
"request": {
"file_mode": 73728,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/bar"
}
},
{
"allowed": false,
"description": "unsupported no mode",
"kind": "CopyFileRequest",
"request": {
"file_mode": 511,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/bar"
}
},
{
"allowed": true,
"description": "directory in top-level shared directory",
"kind": "CopyFileRequest",
"request": {
"file_mode": 16895,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo"
}
},
{
"allowed": false,
"description": "symlink in top-level shared directory",
"kind": "CopyFileRequest",
"request": {
"data": [97, 98, 99],
"file_mode": 41471,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo"
}
},
{
"allowed": true,
"description": "symlink beneath top-level shared directory",
"kind": "CopyFileRequest",
"request": {
"data": [97, 98, 99],
"file_mode": 41471,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/lnk"
}
},
{
"allowed": false,
"description": "symlink pointing up - leading (../abc)",
"kind": "CopyFileRequest",
"request": {
"data": [46, 46, 47, 97, 98, 99],
"file_mode": 41471,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/lnk"
}
},
{
"allowed": false,
"description": "symlink pointing up - middle (a/../../b)",
"kind": "CopyFileRequest",
"request": {
"data": [97, 47, 46, 46, 47, 46, 46, 47, 98],
"file_mode": 41471,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/lnk"
}
},
{
"allowed": false,
"description": "symlink with 0-byte in target (a\\x00/b)",
"kind": "CopyFileRequest",
"request": {
"data": [97, 0, 47, 98],
"file_mode": 41471,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/lnk"
}
},
{
"allowed": false,
"description": "symlink with absolute target (/abc)",
"kind": "CopyFileRequest",
"request": {
"data": [47, 97, 98, 99],
"file_mode": 41471,
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/lnk"
}
}
]

View File

@@ -4362,9 +4362,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
version = "0.1.41"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"pin-project-lite",
"tracing-attributes",
@@ -4373,9 +4373,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.29"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662"
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
@@ -4384,9 +4384,9 @@ dependencies = [
[[package]]
name = "tracing-core"
version = "0.1.34"
version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
]

View File

@@ -184,6 +184,8 @@ pub struct HypervisorInfo {
#[serde(default)]
virtio_fs_daemon: String,
#[serde(default)]
msize_9p: u32,
#[serde(default)]
memory_slots: u32,
#[serde(default)]
pcie_root_port: u32,
@@ -415,6 +417,7 @@ pub fn get_hypervisor_info(
.clone()
.unwrap_or_else(|| String::from("none")),
virtio_fs_daemon: hypervisor_config.shared_fs.virtio_fs_daemon.to_string(),
msize_9p: hypervisor_config.shared_fs.msize_9p,
memory_slots: hypervisor_config.memory_info.memory_slots,
pcie_root_port: hypervisor_config.device_info.pcie_root_port,
hotplug_vfio_on_rootbus: hypervisor_config.device_info.hotplug_vfio_on_root_bus,

View File

@@ -440,46 +440,14 @@ fn add_kata_deploy_warning(config_file: &Path) -> Result<()> {
Ok(())
}
/// Atomically replace a file with a symlink.
///
/// Creates the symlink at a temporary path first, then renames it over the
/// original so the original is preserved if symlink creation fails.
fn atomic_symlink_replace(file_path: &str, symlink_target: &str) -> Result<()> {
let temp_symlink = format!("{}.tmp-link", file_path);
// Clean up any stale temp symlink from a previous interrupted run
if Path::new(&temp_symlink).exists() || Path::new(&temp_symlink).is_symlink() {
let _ = fs::remove_file(&temp_symlink);
}
std::os::unix::fs::symlink(symlink_target, &temp_symlink).with_context(|| {
format!(
"Failed to create temporary symlink {} -> {}",
temp_symlink, symlink_target
)
})?;
fs::rename(&temp_symlink, file_path).map_err(|err| {
let _ = fs::remove_file(&temp_symlink);
anyhow::anyhow!(
"Failed to atomically replace {} with symlink to {}: {}",
file_path,
symlink_target,
err
)
})?;
Ok(())
}
/// Set up the runtime directory structure for a shim.
/// Creates: {config_path}/runtimes/{shim}/
/// {config_path}/runtimes/{shim}/config.d/
/// {config_path}/runtimes/{shim}/configuration-{shim}.toml (copy of original)
///
/// After copying, the original config file is replaced with a symlink pointing
/// to the runtime copy. This way the runtime's ResolvePath / EvalSymlinks resolves
/// the symlink and finds config.d next to the real file in the per-shim directory.
/// Note: We copy the config file instead of symlinking because kata-containers'
/// ResolvePath uses filepath.EvalSymlinks, which would resolve to the original
/// location and look for config.d there instead of in our per-shim directory.
fn setup_runtime_directory(config: &Config, shim: &str) -> Result<()> {
let original_config_dir = format!(
"/host{}",
@@ -498,9 +466,9 @@ fn setup_runtime_directory(config: &Config, shim: &str) -> Result<()> {
fs::create_dir_all(&config_d_dir)
.with_context(|| format!("Failed to create config.d directory: {}", config_d_dir))?;
let config_filename = format!("configuration-{}.toml", shim);
let original_config_file = format!("{}/{}", original_config_dir, config_filename);
let dest_config_file = format!("{}/{}", runtime_config_dir, config_filename);
// Copy the original config file to the runtime directory
let original_config_file = format!("{}/configuration-{}.toml", original_config_dir, shim);
let dest_config_file = format!("{}/configuration-{}.toml", runtime_config_dir, shim);
// Only copy if original exists
if Path::new(&original_config_file).exists() {
@@ -513,7 +481,7 @@ fn setup_runtime_directory(config: &Config, shim: &str) -> Result<()> {
})?;
}
// Copy the base config file to the runtime directory
// Copy the base config file
fs::copy(&original_config_file, &dest_config_file).with_context(|| {
format!(
"Failed to copy config: {} -> {}",
@@ -525,37 +493,13 @@ fn setup_runtime_directory(config: &Config, shim: &str) -> Result<()> {
add_kata_deploy_warning(Path::new(&dest_config_file))?;
info!(" Copied base config: {}", dest_config_file);
let symlink_target = format!("runtimes/{}/{}", shim, config_filename);
atomic_symlink_replace(&original_config_file, &symlink_target)?;
info!(
" Symlinked original config: {} -> {}",
original_config_file, symlink_target
);
}
Ok(())
}
/// Remove the runtime directory for a shim during cleanup.
/// Also removes the symlink at the original config location that was created
/// by setup_runtime_directory.
/// Remove the runtime directory for a shim during cleanup
fn remove_runtime_directory(config: &Config, shim: &str) -> Result<()> {
// Remove the symlink at the original config location (if present)
let original_config_dir = format!(
"/host{}",
utils::get_kata_containers_original_config_path(shim, &config.dest_dir)
);
let original_config_file = format!("{}/configuration-{}.toml", original_config_dir, shim);
let original_path = Path::new(&original_config_file);
if original_path.is_symlink() {
fs::remove_file(&original_config_file).with_context(|| {
format!("Failed to remove config symlink: {}", original_config_file)
})?;
log::debug!("Removed config symlink: {}", original_config_file);
}
let runtime_config_dir = format!(
"/host{}",
utils::get_kata_containers_config_path(shim, &config.dest_dir)
@@ -584,7 +528,7 @@ fn remove_runtime_directory(config: &Config, shim: &str) -> Result<()> {
}
async fn configure_shim_config(config: &Config, shim: &str, container_runtime: &str) -> Result<()> {
// Set up the runtime directory: copy config to per-shim dir and replace original with symlink
// Set up the runtime directory structure with symlink to original config
setup_runtime_directory(config, shim)?;
let runtime_config_dir = format!(
@@ -596,11 +540,11 @@ async fn configure_shim_config(config: &Config, shim: &str, container_runtime: &
let kata_config_file =
Path::new(&runtime_config_dir).join(format!("configuration-{shim}.toml"));
// The configuration file should exist after setup_runtime_directory()
// The configuration file (symlink) should exist after setup_runtime_directory()
if !kata_config_file.exists() {
return Err(anyhow::anyhow!(
"Configuration file not found: {kata_config_file:?}. This file should have been \
copied from the original config. Check that the shim '{}' has a valid configuration \
symlinked from the original config. Check that the shim '{}' has a valid configuration \
file in the artifacts.",
shim
));
@@ -1200,141 +1144,4 @@ mod tests {
"following the symlink should yield the real content"
);
}
#[test]
fn test_atomic_symlink_replace_creates_symlink() {
let tmpdir = tempfile::tempdir().unwrap();
// Create the original file and the target it will point to
let target_dir = tmpdir.path().join("runtimes/qemu");
fs::create_dir_all(&target_dir).unwrap();
let target_file = target_dir.join("configuration-qemu.toml");
fs::write(&target_file, "real config content").unwrap();
let original = tmpdir.path().join("configuration-qemu.toml");
fs::write(&original, "original content").unwrap();
let symlink_target = "runtimes/qemu/configuration-qemu.toml";
atomic_symlink_replace(original.to_str().unwrap(), symlink_target).unwrap();
assert!(original.is_symlink(), "original should now be a symlink");
assert_eq!(
fs::read_link(&original).unwrap().to_str().unwrap(),
symlink_target
);
assert_eq!(
fs::read_to_string(&original).unwrap(),
"real config content",
"reading through the symlink should yield the target's content"
);
}
#[test]
fn test_atomic_symlink_replace_is_idempotent() {
let tmpdir = tempfile::tempdir().unwrap();
let target_dir = tmpdir.path().join("runtimes/qemu");
fs::create_dir_all(&target_dir).unwrap();
let target_file = target_dir.join("configuration-qemu.toml");
fs::write(&target_file, "config content").unwrap();
let original = tmpdir.path().join("configuration-qemu.toml");
fs::write(&original, "original").unwrap();
let symlink_target = "runtimes/qemu/configuration-qemu.toml";
// First call
atomic_symlink_replace(original.to_str().unwrap(), symlink_target).unwrap();
assert!(original.is_symlink());
// Second call (e.g. re-install) should succeed and still be a valid symlink
atomic_symlink_replace(original.to_str().unwrap(), symlink_target).unwrap();
assert!(original.is_symlink());
assert_eq!(
fs::read_link(&original).unwrap().to_str().unwrap(),
symlink_target
);
}
#[test]
fn test_atomic_symlink_replace_cleans_stale_temp() {
let tmpdir = tempfile::tempdir().unwrap();
let original = tmpdir.path().join("configuration-qemu.toml");
fs::write(&original, "original").unwrap();
// Simulate a stale temp symlink from an interrupted previous run
let stale_temp = tmpdir.path().join("configuration-qemu.toml.tmp-link");
std::os::unix::fs::symlink("stale-target", &stale_temp).unwrap();
assert!(stale_temp.is_symlink());
let target_dir = tmpdir.path().join("runtimes/qemu");
fs::create_dir_all(&target_dir).unwrap();
fs::write(target_dir.join("configuration-qemu.toml"), "content").unwrap();
let symlink_target = "runtimes/qemu/configuration-qemu.toml";
atomic_symlink_replace(original.to_str().unwrap(), symlink_target).unwrap();
assert!(original.is_symlink());
assert_eq!(
fs::read_link(&original).unwrap().to_str().unwrap(),
symlink_target
);
// Temp file should not linger
assert!(!stale_temp.exists() && !stale_temp.is_symlink());
}
#[test]
fn test_setup_and_remove_runtime_directory_symlink() {
let tmpdir = tempfile::tempdir().unwrap();
// Simulate the directory layout that setup_runtime_directory expects
// (after copy_artifacts has run), using a Go shim as example.
let defaults_dir = tmpdir.path().join("share/defaults/kata-containers");
fs::create_dir_all(&defaults_dir).unwrap();
let config_filename = "configuration-qemu.toml";
let original_config = defaults_dir.join(config_filename);
fs::write(
&original_config,
"[hypervisor.qemu]\npath = \"/usr/bin/qemu\"",
)
.unwrap();
// Create the runtime directory and copy the config (mimics setup_runtime_directory)
let runtime_dir = defaults_dir.join("runtimes/qemu");
let config_d_dir = runtime_dir.join("config.d");
fs::create_dir_all(&config_d_dir).unwrap();
let dest_config = runtime_dir.join(config_filename);
fs::copy(&original_config, &dest_config).unwrap();
// Atomically replace the original with a symlink
let symlink_target = format!("runtimes/qemu/{}", config_filename);
atomic_symlink_replace(original_config.to_str().unwrap(), &symlink_target).unwrap();
// Verify: original is now a symlink
assert!(original_config.is_symlink());
assert_eq!(
fs::read_link(&original_config).unwrap().to_str().unwrap(),
symlink_target
);
// Verify: reading through the symlink yields the real file content
assert_eq!(
fs::read_to_string(&original_config).unwrap(),
fs::read_to_string(&dest_config).unwrap()
);
// Verify: config.d is next to the real file (the resolved path)
assert!(dest_config.parent().unwrap().join("config.d").is_dir());
// Simulate remove_runtime_directory: remove symlink then runtime dir
assert!(original_config.is_symlink());
fs::remove_file(&original_config).unwrap();
assert!(!original_config.exists() && !original_config.is_symlink());
fs::remove_dir_all(&runtime_dir).unwrap();
assert!(!runtime_dir.exists());
}
}