Skip to content

Commit

Permalink
refactor around uid and gid mapping.
Browse files Browse the repository at this point in the history
  • Loading branch information
utam0k committed Sep 20, 2021
1 parent 4392293 commit 107dd91
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 47 deletions.
27 changes: 16 additions & 11 deletions src/container/builder_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ use crate::{
hooks,
notify_socket::NotifyListener,
process::{args::ContainerArgs, channel, fork, intermediate},
rootless::{self, Rootless},
rootless::Rootless,
syscall::Syscall,
utils,
};
use anyhow::{Context, Result};
use cgroups;
use nix::unistd::Pid;
use oci_spec::runtime::Spec;
use std::{fs, io::Write, os::unix::prelude::RawFd, path::PathBuf};

Expand Down Expand Up @@ -139,17 +140,9 @@ impl<'a> ContainerBuilderImpl<'a> {
// If creating a rootless container, the intermediate process will ask
// the main process to set up uid and gid mapping, once the intermediate
// process enters into a new user namespace.
if self.rootless.is_some() {
if let Some(rootless) = self.rootless.as_ref() {
receiver_from_intermediate.wait_for_mapping_request()?;
log::debug!("write mapping for pid {:?}", intermediate_pid);
let rootless = self.rootless.as_ref().unwrap();
if !rootless.privileged {
// The main process is running as an unprivileged user and cannot write the mapping
// until "deny" has been written to setgroups. See CVE-2014-8989.
utils::write_file(format!("/proc/{}/setgroups", intermediate_pid), "deny")?;
}
rootless::write_uid_mapping(intermediate_pid, self.rootless.as_ref())?;
rootless::write_gid_mapping(intermediate_pid, self.rootless.as_ref())?;
setup_mapping(rootless, intermediate_pid)?;
sender_to_intermediate.mapping_written()?;
}

Expand Down Expand Up @@ -188,3 +181,15 @@ impl<'a> ContainerBuilderImpl<'a> {
Ok(())
}
}

fn setup_mapping(rootless: &Rootless, pid: Pid) -> Result<()> {
log::debug!("write mapping for pid {:?}", pid);
if !rootless.privileged {
// The main process is running as an unprivileged user and cannot write the mapping
// until "deny" has been written to setgroups. See CVE-2014-8989.
utils::write_file(format!("/proc/{}/setgroups", pid), "deny")?;
}
rootless.write_uid_mapping(pid)?;
rootless.write_gid_mapping(pid)?;
Ok(())
}
67 changes: 31 additions & 36 deletions src/rootless.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,19 @@ use std::path::Path;
use std::process::Command;
use std::{env, path::PathBuf};

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Default)]
pub struct Rootless<'a> {
/// Location of the newuidmap binary
pub newuidmap: Option<PathBuf>,
/// Location of the newgidmap binary
pub newgidmap: Option<PathBuf>,
/// Mappings for user ids
pub uid_mappings: Option<&'a Vec<LinuxIdMapping>>,
pub(crate) uid_mappings: Option<&'a Vec<LinuxIdMapping>>,
/// Mappings for group ids
pub gid_mappings: Option<&'a Vec<LinuxIdMapping>>,
pub(crate) gid_mappings: Option<&'a Vec<LinuxIdMapping>>,
/// Info on the user namespaces
user_namespace: Option<LinuxNamespace>,
/// Is rootless container requested by a privileged
/// user
pub(crate) user_namespace: Option<LinuxNamespace>,
/// Is rootless container requested by a privileged user
pub privileged: bool,
}

Expand Down Expand Up @@ -54,6 +53,32 @@ impl<'a> Rootless<'a> {
Ok(None)
}
}

pub fn write_uid_mapping(&self, target_pid: Pid) -> Result<()> {
log::debug!("Write UID mapping for {:?}", target_pid);
if let Some(uid_mappings) = self.uid_mappings {
write_id_mapping(
&format!("/proc/{}/uid_map", target_pid),
uid_mappings,
self.newuidmap.as_deref(),
)
} else {
Ok(())
}
}

pub fn write_gid_mapping(&self, target_pid: Pid) -> Result<()> {
log::debug!("Write GID mapping for {:?}", target_pid);
if let Some(gid_mappings) = self.gid_mappings {
return write_id_mapping(
&format!("/proc/{}/gid_map", target_pid),
gid_mappings,
self.newgidmap.as_deref(),
);
} else {
Ok(())
}
}
}

impl<'a> From<&'a Linux> for Rootless<'a> {
Expand Down Expand Up @@ -199,36 +224,6 @@ fn lookup_map_binary(binary: &str) -> Result<Option<PathBuf>> {
.map(PathBuf::from))
}

pub fn write_uid_mapping(target_pid: Pid, rootless: Option<&Rootless>) -> Result<()> {
log::debug!("Write UID mapping for {:?}", target_pid);
if let Some(rootless) = rootless {
if let Some(uid_mappings) = rootless.uid_mappings {
return write_id_mapping(
&format!("/proc/{}/uid_map", target_pid),
uid_mappings,
rootless.newuidmap.as_deref(),
);
}
}

Ok(())
}

pub fn write_gid_mapping(target_pid: Pid, rootless: Option<&Rootless>) -> Result<()> {
log::debug!("Write GID mapping for {:?}", target_pid);
if let Some(rootless) = rootless {
if let Some(gid_mappings) = rootless.gid_mappings {
return write_id_mapping(
&format!("/proc/{}/gid_map", target_pid),
gid_mappings,
rootless.newgidmap.as_deref(),
);
}
}

Ok(())
}

fn write_id_mapping(
map_file: &str,
mappings: &[LinuxIdMapping],
Expand Down

0 comments on commit 107dd91

Please sign in to comment.