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:
parent
4392293301
commit
107dd91881
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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],
|
||||
|
|
Loading…
Reference in New Issue