1
0
Fork 0
mirror of https://github.com/containers/youki synced 2024-06-01 20:36:12 +02:00

refactor around uid and gid mapping.

This commit is contained in:
utam0k 2021-09-20 16:33:20 +09:00
parent 4392293301
commit 107dd91881
2 changed files with 47 additions and 47 deletions

View File

@ -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};
@ -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()?;
}
@ -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(())
}

View File

@ -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,
}
@ -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> {
@ -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],