mirror of
https://github.com/containers/youki
synced 2024-11-23 01:11:58 +01:00
Change rootless required function and privilege decision
This commit is contained in:
parent
33ebda81ea
commit
7078ad6882
@ -25,6 +25,17 @@ use super::stats::Stats;
|
||||
pub const CGROUP_PROCS: &str = "cgroup.procs";
|
||||
pub const DEFAULT_CGROUP_ROOT: &str = "/sys/fs/cgroup";
|
||||
|
||||
#[cfg(feature = "systemd")]
|
||||
#[inline]
|
||||
fn is_true_root() -> bool {
|
||||
if !nix::unistd::geteuid().is_root() {
|
||||
return false;
|
||||
}
|
||||
let uid_map_path = "/proc/self/uid_map";
|
||||
let content = std::fs::read_to_string(uid_map_path)
|
||||
.unwrap_or_else(|_| panic!("failed to read {}", uid_map_path));
|
||||
content.contains("4294967295")
|
||||
}
|
||||
pub trait CgroupManager {
|
||||
type Error;
|
||||
|
||||
@ -388,7 +399,7 @@ fn create_systemd_cgroup_manager(
|
||||
);
|
||||
}
|
||||
|
||||
let use_system = nix::unistd::geteuid().is_root();
|
||||
let use_system = is_true_root();
|
||||
|
||||
tracing::info!(
|
||||
"systemd cgroup manager with system bus {} will be used",
|
||||
|
@ -13,7 +13,7 @@ use crate::{
|
||||
error::{ErrInvalidSpec, LibcontainerError, MissingSpecError},
|
||||
notify_socket::NOTIFY_FILE,
|
||||
process::args::ContainerType,
|
||||
tty, user_ns,
|
||||
tty, user_ns, utils,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -87,6 +87,11 @@ impl InitContainerBuilder {
|
||||
};
|
||||
|
||||
let user_ns_config = UserNamespaceConfig::new(&spec)?;
|
||||
|
||||
if utils::rootless_required() && !utils::is_in_new_userns() && user_ns_config.is_none() {
|
||||
return Err(LibcontainerError::NoUserNamespace);
|
||||
}
|
||||
|
||||
let config = YoukiConfig::from_spec(&spec, container.id(), user_ns_config.is_some())?;
|
||||
config.save(&container_dir).map_err(|err| {
|
||||
tracing::error!(?container_dir, "failed to save config: {}", err);
|
||||
|
@ -121,6 +121,10 @@ impl TenantContainerBuilder {
|
||||
let use_systemd = self.should_use_systemd(&container);
|
||||
let user_ns_config = UserNamespaceConfig::new(&spec)?;
|
||||
|
||||
if utils::rootless_required() && !utils::is_in_new_userns() && user_ns_config.is_none() {
|
||||
return Err(LibcontainerError::NoUserNamespace);
|
||||
}
|
||||
|
||||
let (read_end, write_end) =
|
||||
pipe2(OFlag::O_CLOEXEC).map_err(LibcontainerError::OtherSyscall)?;
|
||||
|
||||
|
@ -22,6 +22,8 @@ pub enum LibcontainerError {
|
||||
InvalidInput(String),
|
||||
#[error("requires at least one executors")]
|
||||
NoExecutors,
|
||||
#[error("rootless container requires valid user namespace definition")]
|
||||
NoUserNamespace,
|
||||
|
||||
// Invalid inputs
|
||||
#[error(transparent)]
|
||||
|
@ -376,7 +376,8 @@ pub fn container_init_process(
|
||||
})?;
|
||||
}
|
||||
|
||||
let bind_service = namespaces.get(LinuxNamespaceType::User)?.is_some();
|
||||
let bind_service =
|
||||
namespaces.get(LinuxNamespaceType::User)?.is_some() || utils::is_in_new_userns();
|
||||
let rootfs = RootFS::new();
|
||||
rootfs
|
||||
.prepare_rootfs(
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::error::MissingSpecError;
|
||||
use crate::namespaces::{NamespaceError, Namespaces};
|
||||
use crate::utils;
|
||||
use nix::unistd::Pid;
|
||||
use oci_spec::runtime::{Linux, LinuxIdMapping, LinuxNamespace, LinuxNamespaceType, Mount, Spec};
|
||||
use std::fs;
|
||||
@ -85,8 +86,6 @@ type Result<T> = std::result::Result<T, UserNamespaceError>;
|
||||
pub enum ValidateSpecError {
|
||||
#[error(transparent)]
|
||||
MissingSpec(#[from] crate::error::MissingSpecError),
|
||||
#[error("rootless container requires valid user namespace definition")]
|
||||
NoUserNamespace, // TODO fix this while fixing podman
|
||||
#[error("new user namespace requires valid uid mappings")]
|
||||
NoUIDMappings,
|
||||
#[error("new user namespace requires valid gid mappings")]
|
||||
@ -152,13 +151,6 @@ impl UserNamespaceConfig {
|
||||
.get(LinuxNamespaceType::User)
|
||||
.map_err(ValidateSpecError::Namespaces)?;
|
||||
|
||||
// If conditions requires us to use rootless, we must either create a new
|
||||
// user namespace or enter an existing.
|
||||
// TODO FIX THIS FOR ROOTLESS
|
||||
if rootless_required() && user_namespace.is_none() {
|
||||
return Err(UserNamespaceError::NoUserNamespace);
|
||||
}
|
||||
|
||||
if user_namespace.is_some() && user_namespace.unwrap().path().is_none() {
|
||||
tracing::debug!("container with new user namespace should be created");
|
||||
|
||||
@ -225,22 +217,12 @@ impl TryFrom<&Linux> for UserNamespaceConfig {
|
||||
uid_mappings: linux.uid_mappings().to_owned(),
|
||||
gid_mappings: linux.gid_mappings().to_owned(),
|
||||
user_namespace: user_namespace.cloned(),
|
||||
privileged: nix::unistd::geteuid().is_root(),
|
||||
privileged: !utils::rootless_required(),
|
||||
id_mapper: UserNamespaceIDMapper::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if rootless mode should be used
|
||||
// TODO fix this along with podman
|
||||
pub fn rootless_required() -> bool {
|
||||
if !nix::unistd::geteuid().is_root() {
|
||||
return true;
|
||||
}
|
||||
|
||||
matches!(std::env::var("YOUKI_USE_ROOTLESS").as_deref(), Ok("true"))
|
||||
}
|
||||
|
||||
pub fn unprivileged_user_ns_enabled() -> Result<bool> {
|
||||
let user_ns_sysctl = Path::new("/proc/sys/kernel/unprivileged_userns_clone");
|
||||
if !user_ns_sysctl.exists() {
|
||||
@ -269,10 +251,6 @@ fn validate_spec_for_new_user_ns(spec: &Spec) -> std::result::Result<(), Validat
|
||||
"validating spec for container with new user namespace"
|
||||
);
|
||||
let linux = spec.linux().as_ref().ok_or(MissingSpecError::Linux)?;
|
||||
let namespaces = Namespaces::try_from(linux.namespaces().as_ref())?;
|
||||
if namespaces.get(LinuxNamespaceType::User)?.is_none() {
|
||||
return Err(ValidateSpecError::NoUserNamespace);
|
||||
}
|
||||
|
||||
let gid_mappings = linux
|
||||
.gid_mappings()
|
||||
@ -303,9 +281,8 @@ fn validate_spec_for_new_user_ns(spec: &Spec) -> std::result::Result<(), Validat
|
||||
.as_ref()
|
||||
.and_then(|process| process.user().additional_gids().as_ref())
|
||||
{
|
||||
let privileged = nix::unistd::geteuid().is_root();
|
||||
let privileged = !utils::rootless_required();
|
||||
|
||||
// TODO fix this along with fixes for podman
|
||||
match (privileged, additional_gids.is_empty()) {
|
||||
(true, false) => {
|
||||
for gid in additional_gids {
|
||||
@ -516,19 +493,6 @@ mod tests {
|
||||
.size(10_u32)
|
||||
.build()?];
|
||||
|
||||
let linux_no_userns = LinuxBuilder::default()
|
||||
.namespaces(vec![])
|
||||
.uid_mappings(uid_mappings.clone())
|
||||
.gid_mappings(gid_mappings.clone())
|
||||
.build()?;
|
||||
assert!(validate_spec_for_new_user_ns(
|
||||
&SpecBuilder::default()
|
||||
.linux(linux_no_userns)
|
||||
.build()
|
||||
.unwrap()
|
||||
)
|
||||
.is_err());
|
||||
|
||||
let linux_uid_empty = LinuxBuilder::default()
|
||||
.namespaces(vec![userns.clone()])
|
||||
.uid_mappings(vec![])
|
||||
|
@ -258,6 +258,21 @@ pub fn ensure_procfs(path: &Path) -> Result<(), EnsureProcfsError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_in_new_userns() -> bool {
|
||||
let uid_map_path = "/proc/self/uid_map";
|
||||
let content = std::fs::read_to_string(uid_map_path)
|
||||
.unwrap_or_else(|_| panic!("failed to read {}", uid_map_path));
|
||||
!content.contains("4294967295")
|
||||
}
|
||||
|
||||
/// Checks if rootless mode needs to be used
|
||||
pub fn rootless_required() -> bool {
|
||||
if !nix::unistd::geteuid().is_root() {
|
||||
return true;
|
||||
}
|
||||
is_in_new_userns()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -73,7 +73,13 @@ where
|
||||
let log_level_filter = tracing_subscriber::filter::LevelFilter::from(level);
|
||||
let log_format = detect_log_format(config.log_format.as_deref())
|
||||
.with_context(|| "failed to detect log format")?;
|
||||
let systemd_journald = if config.systemd_log {
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
let journald = true;
|
||||
#[cfg(not(debug_assertions))]
|
||||
let journald = config.systemd_log;
|
||||
|
||||
let systemd_journald = if journald {
|
||||
Some(tracing_journald::layer()?.with_syslog_identifier("youki".to_string()))
|
||||
} else {
|
||||
None
|
||||
|
@ -1,6 +1,6 @@
|
||||
use anyhow::{bail, Result};
|
||||
use libcontainer::user_ns::rootless_required;
|
||||
use libcontainer::utils::create_dir_all_with_mode;
|
||||
use libcontainer::utils::rootless_required;
|
||||
use nix::libc;
|
||||
use nix::sys::stat::Mode;
|
||||
use nix::unistd::getuid;
|
||||
|
Loading…
Reference in New Issue
Block a user