runk: Allow runk to launch a container without pid namespace

Allow runk to launch a container even though users don't specify the
pid namespace in `config.json` because general container runtimes
such as runc also can launch a container without the namespace.
On the other hand, Kata Containers doesn't allow it due to security issue
so this feature should be enabled in only runk.

Fixes: #7168

Signed-off-by: Manabu Sugimoto <Manabu.Sugimoto@sony.com>
This commit is contained in:
Manabu Sugimoto 2023-06-15 01:39:53 +09:00 committed by Chethan Suresh
parent ce8e3cc091
commit f1d8de9be6

View File

@ -80,6 +80,7 @@ const CLOG_FD: &str = "CLOG_FD";
const FIFO_FD: &str = "FIFO_FD"; const FIFO_FD: &str = "FIFO_FD";
const HOME_ENV_KEY: &str = "HOME"; const HOME_ENV_KEY: &str = "HOME";
const PIDNS_FD: &str = "PIDNS_FD"; const PIDNS_FD: &str = "PIDNS_FD";
const PIDNS_ENABLED: &str = "PIDNS_ENABLED";
const CONSOLE_SOCKET_FD: &str = "CONSOLE_SOCKET_FD"; const CONSOLE_SOCKET_FD: &str = "CONSOLE_SOCKET_FD";
#[derive(Debug)] #[derive(Debug)]
@ -280,6 +281,17 @@ pub struct SyncPc {
pid: pid_t, pid: pid_t,
} }
#[derive(Debug, Clone)]
pub struct PidNs {
enabled: bool,
fd: Option<i32>,
}
impl PidNs {
pub fn new(enabled: bool, fd: Option<i32>) -> Self {
Self { enabled, fd }
}
}
pub trait Container: BaseContainer { pub trait Container: BaseContainer {
fn pause(&mut self) -> Result<()>; fn pause(&mut self) -> Result<()>;
fn resume(&mut self) -> Result<()>; fn resume(&mut self) -> Result<()>;
@ -339,16 +351,20 @@ fn do_init_child(cwfd: RawFd) -> Result<()> {
let crfd = std::env::var(CRFD_FD)?.parse::<i32>().unwrap(); let crfd = std::env::var(CRFD_FD)?.parse::<i32>().unwrap();
let cfd_log = std::env::var(CLOG_FD)?.parse::<i32>().unwrap(); let cfd_log = std::env::var(CLOG_FD)?.parse::<i32>().unwrap();
// get the pidns fd from parent, if parent had passed the pidns fd, if std::env::var(PIDNS_ENABLED)?.eq(format!("{}", true).as_str()) {
// then get it and join in this pidns; otherwise, create a new pidns // get the pidns fd from parent, if parent had passed the pidns fd,
// by unshare from the parent pidns. // then get it and join in this pidns; otherwise, create a new pidns
match std::env::var(PIDNS_FD) { // by unshare from the parent pidns.
Ok(fd) => { match std::env::var(PIDNS_FD) {
let pidns_fd = fd.parse::<i32>().context("get parent pidns fd")?; Ok(fd) => {
sched::setns(pidns_fd, CloneFlags::CLONE_NEWPID).context("failed to join pidns")?; let pidns_fd = fd.parse::<i32>().context("get parent pidns fd")?;
let _ = unistd::close(pidns_fd); sched::setns(pidns_fd, CloneFlags::CLONE_NEWPID).context("failed to join pidns")?;
let _ = unistd::close(pidns_fd);
}
Err(_e) => {
sched::unshare(CloneFlags::CLONE_NEWPID)?;
}
} }
Err(_e) => sched::unshare(CloneFlags::CLONE_NEWPID)?,
} }
match unsafe { fork() } { match unsafe { fork() } {
@ -983,9 +999,13 @@ impl BaseContainer for LinuxContainer {
} }
let pidns = get_pid_namespace(&self.logger, linux)?; let pidns = get_pid_namespace(&self.logger, linux)?;
#[cfg(not(feature = "standard-oci-runtime"))]
if !pidns.enabled {
return Err(anyhow!("cannot find the pid ns"));
}
defer!(if let Some(pid) = pidns { defer!(if let Some(fd) = pidns.fd {
let _ = unistd::close(pid); let _ = unistd::close(fd);
}); });
let exec_path = std::env::current_exe()?; let exec_path = std::env::current_exe()?;
@ -1008,14 +1028,15 @@ impl BaseContainer for LinuxContainer {
.env(CRFD_FD, format!("{}", crfd)) .env(CRFD_FD, format!("{}", crfd))
.env(CWFD_FD, format!("{}", cwfd)) .env(CWFD_FD, format!("{}", cwfd))
.env(CLOG_FD, format!("{}", cfd_log)) .env(CLOG_FD, format!("{}", cfd_log))
.env(CONSOLE_SOCKET_FD, console_name); .env(CONSOLE_SOCKET_FD, console_name)
.env(PIDNS_ENABLED, format!("{}", pidns.enabled));
if p.init { if p.init {
child = child.env(FIFO_FD, format!("{}", fifofd)); child = child.env(FIFO_FD, format!("{}", fifofd));
} }
if pidns.is_some() { if pidns.fd.is_some() {
child = child.env(PIDNS_FD, format!("{}", pidns.unwrap())); child = child.env(PIDNS_FD, format!("{}", pidns.fd.unwrap()));
} }
child.spawn()?; child.spawn()?;
@ -1249,11 +1270,11 @@ pub fn update_namespaces(logger: &Logger, spec: &mut Spec, init_pid: RawFd) -> R
Ok(()) Ok(())
} }
fn get_pid_namespace(logger: &Logger, linux: &Linux) -> Result<Option<RawFd>> { fn get_pid_namespace(logger: &Logger, linux: &Linux) -> Result<PidNs> {
for ns in &linux.namespaces { for ns in &linux.namespaces {
if ns.r#type == "pid" { if ns.r#type == "pid" {
if ns.path.is_empty() { if ns.path.is_empty() {
return Ok(None); return Ok(PidNs::new(true, None));
} }
let fd = let fd =
@ -1269,11 +1290,11 @@ fn get_pid_namespace(logger: &Logger, linux: &Linux) -> Result<Option<RawFd>> {
e e
})?; })?;
return Ok(Some(fd)); return Ok(PidNs::new(true, Some(fd)));
} }
} }
Err(anyhow!("cannot find the pid ns")) Ok(PidNs::new(false, None))
} }
fn is_userns_enabled(linux: &Linux) -> bool { fn is_userns_enabled(linux: &Linux) -> bool {