runtime-rs: Properly parse containerd runtime options to extract ConfigPath

The runtime-rs shim was failing to load its configuration when deployed
via kata-deploy because it couldn't correctly parse the ConfigPath passed
by containerd. The previous implementation naively skipped the first 2
bytes of the options and interpreted the rest as a UTF-8 string, which
doesn't work since containerd passes a properly serialized protobuf
message of type runtimeoptions.v1.Options.

This change adds the runtimeoptions.proto definition to the protocols
crate and updates the load_config function to correctly deserialize the
protobuf message and extract the config_path field, matching how the Go
runtime handles this via typeurl.UnmarshalAny.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
This commit is contained in:
Fabiano Fidêncio
2026-02-05 20:30:13 +01:00
parent cb652e0da1
commit 34199b09eb
7 changed files with 44 additions and 7 deletions

2
Cargo.lock generated
View File

@@ -4047,6 +4047,8 @@ dependencies = [
"persist",
"procfs 0.12.0",
"prometheus",
"protobuf",
"protocols",
"resource",
"runtime-spec",
"serde_json",

View File

@@ -191,6 +191,7 @@ fn real_main() -> Result<(), std::io::Error> {
"protos/oci.proto",
"protos/types.proto",
"protos/csi.proto",
"protos/runtimeoptions.proto",
],
false,
)?;

View File

@@ -0,0 +1,20 @@
// Copyright (c) 2024 The containerd Authors
// SPDX-License-Identifier: Apache-2.0
//
// This proto definition is based on containerd's runtimeoptions/v1/api.proto
// https://github.com/containerd/containerd/blob/main/api/types/runtimeoptions/v1/api.proto
syntax = "proto3";
package runtimeoptions.v1;
message Options {
// TypeUrl specifies the type of the content inside the config file.
string type_url = 1;
// ConfigPath specifies the filesystem location of the config file
// used by the runtime.
string config_path = 2;
// Blob specifies an in-memory TOML blob passed from containerd's configuration section
// for this runtime. This will be used if config_path is not specified.
bytes config_body = 3;
}

View File

@@ -22,6 +22,7 @@ pub mod remote;
pub mod remote_ttrpc;
#[cfg(feature = "async")]
pub mod remote_ttrpc_async;
pub mod runtimeoptions;
#[cfg(feature = "with-serde")]
mod serde_config;
pub mod trans;

View File

@@ -38,6 +38,8 @@ oci-spec = { workspace = true }
agent = { workspace = true }
common = { workspace = true }
kata-types = { workspace = true }
protocols = { workspace = true }
protobuf = { workspace = true }
kata-sys-util = { workspace = true }
logging = { workspace = true }
runtime-spec = { workspace = true }

View File

@@ -10,7 +10,7 @@ license = { workspace = true }
[dependencies]
anyhow = { workspace = true }
async-trait = { workspace = true }
containerd-shim-protos = { workspace = true }
containerd-shim-protos = { workspace = true, features = ["sandbox"] }
lazy_static = { workspace = true }
nix = { workspace = true }
protobuf = { workspace = true }

View File

@@ -39,13 +39,14 @@ use resource::{
};
use runtime_spec as spec;
use shim_interface::shim_mgmt::ERR_NO_SHIM_SERVER;
use protobuf::Message as ProtobufMessage;
use std::{
collections::HashMap,
env,
ops::Deref,
os::unix::fs::{chown, MetadataExt},
path::{Path, PathBuf},
str::{from_utf8, FromStr},
str::FromStr,
sync::Arc,
time::SystemTime,
};
@@ -700,11 +701,21 @@ fn load_config(an: &HashMap<String, String>, option: &Option<Vec<u8>>) -> Result
} else if let Ok(path) = std::env::var(KATA_CONF_FILE) {
path
} else if let Some(option) = option {
// get rid of the special characters in options to get the config path
if option.len() > 2 {
from_utf8(&option[2..])?.to_string()
} else {
String::from("")
// Parse the containerd runtime options protobuf message to extract the config path.
// The options are passed as a serialized runtimeoptions.v1.Options protobuf message
// from containerd's configuration (e.g., [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata.options]).
match <protocols::runtimeoptions::Options as ProtobufMessage>::parse_from_bytes(option) {
Ok(opts) => opts.config_path,
Err(e) => {
// Log the error but don't fail - fall back to default config paths
let logger = slog::Logger::clone(&slog_scope::logger());
slog::warn!(
logger,
"failed to parse containerd runtime options: {}, falling back to default config paths",
e
);
String::from("")
}
}
} else {
String::from("")