From 7ba26b149c8375295b2062cce2074a9c467a518d Mon Sep 17 00:00:00 2001 From: lengrongfu <1275177125@qq.com> Date: Tue, 28 Feb 2023 23:39:55 +0800 Subject: [PATCH] feat Add container id validate Signed-off-by: lengrongfu <1275177125@qq.com> --- crates/libcontainer/src/container/builder.rs | 59 +++++++++++++++++++- crates/youki/src/commands/create.rs | 1 + crates/youki/src/commands/exec.rs | 1 + crates/youki/src/commands/run.rs | 1 + 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/crates/libcontainer/src/container/builder.rs b/crates/libcontainer/src/container/builder.rs index 95a3989ba..d7d631a1b 100644 --- a/crates/libcontainer/src/container/builder.rs +++ b/crates/libcontainer/src/container/builder.rs @@ -1,5 +1,5 @@ use crate::{syscall::Syscall, utils::PathBufExt}; -use anyhow::{Context, Result}; +use anyhow::{anyhow, Context, Result}; use std::path::PathBuf; use super::{init_builder::InitContainerBuilder, tenant_builder::TenantContainerBuilder}; @@ -50,7 +50,6 @@ impl<'a> ContainerBuilder<'a> { /// ``` pub fn new(container_id: String, syscall: &'a dyn Syscall) -> Self { let root_path = PathBuf::from("/run/youki"); - Self { container_id, root_path, @@ -61,6 +60,40 @@ impl<'a> ContainerBuilder<'a> { } } + /// validate_id checks if the supplied container ID is valid, returning + /// the ErrInvalidID in case it is not. + /// + /// The format of valid ID was never formally defined, instead the code + /// was modified to allow or disallow specific characters. + /// + /// Currently, a valid ID is a non-empty string consisting only of + /// the following characters: + /// - uppercase (A-Z) and lowercase (a-z) Latin letters; + /// - digits (0-9); + /// - underscore (_); + /// - plus sign (+); + /// - minus sign (-); + /// - period (.). + /// + /// In addition, IDs that can't be used to represent a file name + /// (such as . or ..) are rejected. + pub fn validate_id(self) -> Result { + let container_id = self.container_id.clone(); + if container_id.is_empty() { + return Err(anyhow!("invalid container ID format: {:?}", container_id)); + } + if container_id == "." || container_id == ".." { + return Err(anyhow!("invalid container ID format: {:?}", container_id)); + } + for c in container_id.chars() { + match c { + 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '+' | '-' | '.' => (), + _ => return Err(anyhow!("invalid container ID format: {:?}", container_id)), + } + } + Ok(self) + } + /// Transforms this builder into a tenant builder /// # Example /// @@ -227,4 +260,26 @@ mod tests { Ok(()) } + + #[test] + fn test_validate_id() -> Result<()> { + let syscall = create_syscall(); + // validate container_id + let result = ContainerBuilder::new("$#".to_owned(), syscall.as_ref()).validate_id(); + assert!(result.is_err()); + + let result = ContainerBuilder::new(".".to_owned(), syscall.as_ref()).validate_id(); + assert!(result.is_err()); + + let result = ContainerBuilder::new("..".to_owned(), syscall.as_ref()).validate_id(); + assert!(result.is_err()); + + let result = ContainerBuilder::new("...".to_owned(), syscall.as_ref()).validate_id(); + assert!(result.is_ok()); + + let result = + ContainerBuilder::new("74f1a4cb3801".to_owned(), syscall.as_ref()).validate_id(); + assert!(result.is_ok()); + Ok(()) + } } diff --git a/crates/youki/src/commands/create.rs b/crates/youki/src/commands/create.rs index 7d6d37672..2343aed58 100644 --- a/crates/youki/src/commands/create.rs +++ b/crates/youki/src/commands/create.rs @@ -17,6 +17,7 @@ pub fn create(args: Create, root_path: PathBuf, systemd_cgroup: bool) -> Result< .with_console_socket(args.console_socket.as_ref()) .with_root_path(root_path)? .with_preserved_fds(args.preserve_fds) + .validate_id()? .as_init(&args.bundle) .with_systemd(systemd_cgroup) .build()?; diff --git a/crates/youki/src/commands/exec.rs b/crates/youki/src/commands/exec.rs index d8b83a0a9..c0438e2c5 100644 --- a/crates/youki/src/commands/exec.rs +++ b/crates/youki/src/commands/exec.rs @@ -11,6 +11,7 @@ pub fn exec(args: Exec, root_path: PathBuf) -> Result { .with_root_path(root_path)? .with_console_socket(args.console_socket.as_ref()) .with_pid_file(args.pid_file.as_ref())? + .validate_id()? .as_tenant() .with_detach(args.detach) .with_cwd(args.cwd.as_ref()) diff --git a/crates/youki/src/commands/run.rs b/crates/youki/src/commands/run.rs index ef74cd97d..fd1bdca1f 100644 --- a/crates/youki/src/commands/run.rs +++ b/crates/youki/src/commands/run.rs @@ -11,6 +11,7 @@ pub fn run(args: Run, root_path: PathBuf, systemd_cgroup: bool) -> Result<()> { .with_console_socket(args.console_socket.as_ref()) .with_root_path(root_path)? .with_preserved_fds(args.preserve_fds) + .validate_id()? .as_init(&args.bundle) .with_systemd(systemd_cgroup) .build()?;