diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c1d2d821..3c6532389 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- #891 - support custom user namespace overrides by setting the `CROSS_CONTAINER_USER_NAMESPACE` environment variable. - #890 - support rootless docker via the `CROSS_ROOTLESS_CONTAINER_ENGINE` environment variable. ### Changed diff --git a/src/docker/local.rs b/src/docker/local.rs index d88f191b9..360272abf 100644 --- a/src/docker/local.rs +++ b/src/docker/local.rs @@ -31,7 +31,7 @@ pub(crate) fn run( cmd.args(args); let mut docker = subcommand(engine, "run"); - docker.args(&["--userns", "host"]); + docker_userns(&mut docker); docker_envvars(&mut docker, config, target, msg_info)?; let mount_volumes = docker_mount( diff --git a/src/docker/remote.rs b/src/docker/remote.rs index 4e49ea0b5..46a8b2597 100644 --- a/src/docker/remote.rs +++ b/src/docker/remote.rs @@ -815,7 +815,7 @@ pub(crate) fn run( // 3. create our start container command here let mut docker = subcommand(engine, "run"); - docker.args(&["--userns", "host"]); + docker_userns(&mut docker); docker.args(&["--name", &container]); docker.args(&["-v", &format!("{}:{mount_prefix}", volume.as_ref())]); docker_envvars(&mut docker, config, target, msg_info)?; diff --git a/src/docker/shared.rs b/src/docker/shared.rs index 9a4b0afc3..fb3f6b31c 100644 --- a/src/docker/shared.rs +++ b/src/docker/shared.rs @@ -183,14 +183,14 @@ pub(crate) fn register(engine: &Engine, target: &Target, msg_info: MessageInfo) binfmt-support qemu-user-static" }; - subcommand(engine, "run") - .args(&["--userns", "host"]) - .arg("--privileged") - .arg("--rm") - .arg(UBUNTU_BASE) - .args(&["sh", "-c", cmd]) - .run(msg_info, false) - .map_err(Into::into) + let mut docker = subcommand(engine, "run"); + docker_userns(&mut docker); + docker.arg("--privileged"); + docker.arg("--rm"); + docker.arg(UBUNTU_BASE); + docker.args(&["sh", "-c", cmd]); + + docker.run(msg_info, false).map_err(Into::into) } fn validate_env_var(var: &str) -> Result<(&str, Option<&str>)> { @@ -414,6 +414,17 @@ pub(crate) fn docker_user_id(docker: &mut Command, engine_type: EngineType) { } } +pub(crate) fn docker_userns(docker: &mut Command) { + let userns = match env::var("CROSS_CONTAINER_USER_NAMESPACE").ok().as_deref() { + Some("none") => None, + None | Some("auto") => Some("host".to_string()), + Some(ns) => Some(ns.to_string()), + }; + if let Some(ns) = userns { + docker.args(&["--userns", &ns]); + } +} + #[allow(unused_mut, clippy::let_and_return)] pub(crate) fn docker_seccomp( docker: &mut Command, @@ -702,6 +713,41 @@ mod tests { } } + #[test] + fn test_docker_userns() { + let var = "CROSS_CONTAINER_USER_NAMESPACE"; + let old = env::var(var); + env::remove_var(var); + + let host = "\"engine\" \"--userns\" \"host\"".to_string(); + let custom = "\"engine\" \"--userns\" \"custom\"".to_string(); + let none = "\"engine\"".to_string(); + + let test = |expected| { + let mut cmd = Command::new("engine"); + docker_userns(&mut cmd); + assert_eq!(expected, &format!("{cmd:?}")); + }; + test(&host); + + env::set_var(var, "auto"); + test(&host); + + env::set_var(var, "none"); + test(&none); + + env::set_var(var, "host"); + test(&host); + + env::set_var(var, "custom"); + test(&custom); + + match old { + Ok(v) => env::set_var(var, v), + Err(_) => env::remove_var(var), + } + } + mod mount_finder { use super::*;