Skip to content

Commit

Permalink
libcontainer: support set stdio for container
Browse files Browse the repository at this point in the history
currently the container can only inherit stdios from it's parent
process, the one who create container with libcontainer can not set
stdios to a different file.

Signed-off-by: Abel Feng <fshb1988@gmail.com>
  • Loading branch information
abel-von committed Oct 25, 2024
1 parent eaaca64 commit 4b9f469
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 1 deletion.
94 changes: 94 additions & 0 deletions crates/libcontainer/src/container/builder.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::os::fd::RawFd;
use std::path::PathBuf;

use super::init_builder::InitContainerBuilder;
Expand All @@ -24,6 +25,12 @@ pub struct ContainerBuilder {
/// The function that actually runs on the container init process. Default
/// is to execute the specified command in the oci spec.
pub(super) executor: Box<dyn Executor>,
// RawFd set to stdin of the container init process.
pub stdin: Option<RawFd>,
// RawFd set to stdout of the container init process.
pub stdout: Option<RawFd>,
// RawFd set to stderr of the container init process.
pub stderr: Option<RawFd>,
}

/// Builder that can be used to configure the common properties of
Expand Down Expand Up @@ -70,6 +77,9 @@ impl ContainerBuilder {
console_socket: None,
preserve_fds: 0,
executor: workload::default::get_executor(),
stdin: None,
stdout: None,
stderr: None,
}
}

Expand Down Expand Up @@ -257,6 +267,90 @@ impl ContainerBuilder {
self.executor = Box::new(executor);
self
}

/// Sets the stdin of the container, for those who use libcontainer as an library,
/// the container stdin may not have to be set to an opened file descriptor
/// rather than the stdin of the currrent process.

Check warning on line 273 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

"currrent" should be "current".

Check failure on line 273 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

`currrent` should be `current`
/// # Example
///
/// ```no_run
/// # use libcontainer::container::builder::ContainerBuilder;
/// # use libcontainer::syscall::syscall::SyscallType;
/// # use libcontainer::workload::default::DefaultExecutor;
/// # use libc;
/// # use std::os::fd::IntoRawFd;
///
/// let f = OpenOptions::new()
/// .read(true)

Check failure on line 284 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / tests (x86_64, gnu)

failed to resolve: use of undeclared type `OpenOptions`

Check failure on line 284 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / tests (x86_64, musl)

failed to resolve: use of undeclared type `OpenOptions`
/// .custom_flags(libc::O_NONBLOCK)
/// .open("/path/to/stdin_pipe")?;
///
/// ContainerBuilder::new(
/// "74f1a4cb3801".to_owned(),
/// SyscallType::default(),
/// )
/// .with_stdin(f.into_raw_fd());
/// ```
pub fn with_stdin(mut self, stdin: RawFd) -> Self {
self.stdin = Some(stdin);
self
}

/// Sets the stdout of the container, for those who use libcontainer as an library,
/// the container stdout may not have to be set to an opened file descriptor
/// rather than the stdout of the currrent process.

Check warning on line 301 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

"currrent" should be "current".

Check failure on line 301 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

`currrent` should be `current`
/// # Example
///
/// ```no_run
/// # use libcontainer::container::builder::ContainerBuilder;
/// # use libcontainer::syscall::syscall::SyscallType;
/// # use libcontainer::workload::default::DefaultExecutor;
/// # use libc;
/// # use std::os::fd::IntoRawFd;
///
/// let f = OpenOptions::new()
/// .read(true)

Check failure on line 312 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / tests (x86_64, gnu)

failed to resolve: use of undeclared type `OpenOptions`

Check failure on line 312 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / tests (x86_64, musl)

failed to resolve: use of undeclared type `OpenOptions`
/// .custom_flags(libc::O_NONBLOCK)
/// .open("/path/to/stdout_pipe")?;
///
/// ContainerBuilder::new(
/// "74f1a4cb3801".to_owned(),
/// SyscallType::default(),
/// )
/// .with_stdout(f.into_raw_fd());
/// ```
pub fn with_stdout(mut self, stdout: RawFd) -> Self {
self.stdout = Some(stdout);
self
}

/// Sets the stderr of the container, for those who use libcontainer as an library,
/// the container stderr may not have to be set to an opened file descriptor
/// rather than the stderr of the currrent process.

Check warning on line 329 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

"currrent" should be "current".

Check failure on line 329 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

`currrent` should be `current`
/// # Example
///
/// ```no_run
/// # use libcontainer::container::builder::ContainerBuilder;
/// # use libcontainer::syscall::syscall::SyscallType;
/// # use libcontainer::workload::default::DefaultExecutor;
/// # use libc;
/// # use std::os::fd::IntoRawFd;
///
/// let f = OpenOptions::new()
/// .read(true)

Check failure on line 340 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / tests (x86_64, gnu)

failed to resolve: use of undeclared type `OpenOptions`

Check failure on line 340 in crates/libcontainer/src/container/builder.rs

View workflow job for this annotation

GitHub Actions / tests (x86_64, musl)

failed to resolve: use of undeclared type `OpenOptions`
/// .custom_flags(libc::O_NONBLOCK)
/// .open("/path/to/stderr_pipe")?;
///
/// ContainerBuilder::new(
/// "74f1a4cb3801".to_owned(),
/// SyscallType::default(),
/// )
/// .with_stderr(f.into_raw_fd());
/// ```
pub fn with_stderr(mut self, stderr: RawFd) -> Self {
self.stderr = Some(stderr);
self
}
}

#[cfg(test)]
Expand Down
9 changes: 9 additions & 0 deletions crates/libcontainer/src/container/builder_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ pub(super) struct ContainerBuilderImpl {
pub detached: bool,
/// Default executes the specified execution of a generic command
pub executor: Box<dyn Executor>,
// RawFd set to stdin of the container init process.
pub stdin: Option<RawFd>,
// RawFd set to stdout of the container init process.
pub stdout: Option<RawFd>,
// RawFd set to stderr of the container init process.
pub stderr: Option<RawFd>,
}

impl ContainerBuilderImpl {
Expand Down Expand Up @@ -154,6 +160,9 @@ impl ContainerBuilderImpl {
cgroup_config,
detached: self.detached,
executor: self.executor.clone(),
stdin: self.stdin,
stdout: self.stdout,
stderr: self.stderr,
};

let (init_pid, need_to_clean_up_intel_rdt_dir) =
Expand Down
3 changes: 3 additions & 0 deletions crates/libcontainer/src/container/init_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ impl InitContainerBuilder {
preserve_fds: self.base.preserve_fds,
detached: self.detached,
executor: self.base.executor,
stdin: self.base.stdin,
stdout: self.base.stdout,
stderr: self.base.stderr,
};

builder_impl.create()?;
Expand Down
3 changes: 3 additions & 0 deletions crates/libcontainer/src/container/tenant_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ impl TenantContainerBuilder {
preserve_fds: self.base.preserve_fds,
detached: self.detached,
executor: self.base.executor,
stdin: self.base.stdin,
stdout: self.base.stdout,
stderr: self.base.stderr,
};

let pid = builder_impl.create()?;
Expand Down
6 changes: 6 additions & 0 deletions crates/libcontainer/src/process/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,10 @@ pub struct ContainerArgs {
pub detached: bool,
/// Manage the functions that actually run on the container
pub executor: Box<dyn Executor>,
// RawFd set to stdin of the container init process.
pub stdin: Option<RawFd>,
// RawFd set to stdout of the container init process.
pub stdout: Option<RawFd>,
// RawFd set to stderr of the container init process.
pub stderr: Option<RawFd>,
}
12 changes: 11 additions & 1 deletion crates/libcontainer/src/process/container_init_process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use nc;
use nix::mount::MsFlags;
use nix::sched::CloneFlags;
use nix::sys::stat::Mode;
use nix::unistd::{self, setsid, Gid, Uid};
use nix::unistd::{self, dup2, setsid, Gid, Uid};
use oci_spec::runtime::{
IOPriorityClass, LinuxIOPriority, LinuxNamespaceType, LinuxSchedulerFlag, LinuxSchedulerPolicy,
Scheduler, Spec, User,
Expand Down Expand Up @@ -304,6 +304,16 @@ pub fn container_init_process(
tracing::error!(?err, "failed to set up tty");
InitProcessError::Tty(err)
})?;
} else {
if let Some(stdin) = args.stdin {
dup2(stdin, 0).map_err(InitProcessError::NixOther)?;
}
if let Some(stdout) = args.stdout {
dup2(stdout, 1).map_err(InitProcessError::NixOther)?;
}
if let Some(stderr) = args.stderr {
dup2(stderr, 2).map_err(InitProcessError::NixOther)?;
}
}

apply_rest_namespaces(&namespaces, spec, syscall.as_ref())?;
Expand Down

0 comments on commit 4b9f469

Please sign in to comment.