From 2b278f48460453691c63ad81b0c87b50d8b18979 Mon Sep 17 00:00:00 2001 From: Phil Estes Date: Mon, 21 Mar 2016 21:30:21 -0400 Subject: [PATCH] Allow net and IPC namespaces to be shared when userns=on Now that the namespace sharing code via runc is vendored with the containerd changes, we can disable the restrictions on container to container net and IPC namespace sharing when the daemon has user namespaces enabled. Docker-DCO-1.1-Signed-off-by: Phil Estes (github: estesp) --- daemon/daemon_unix.go | 7 ++---- daemon/oci_linux.go | 34 ++++++++++++++++++++-------- docs/reference/commandline/daemon.md | 4 +--- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index b6e60ff77c..e9b78ac76d 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -518,15 +518,12 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. if hostConfig.Privileged { return warnings, fmt.Errorf("Privileged mode is incompatible with user namespaces") } - if hostConfig.NetworkMode.IsHost() || hostConfig.NetworkMode.IsContainer() { - return warnings, fmt.Errorf("Cannot share the host or a container's network namespace when user namespaces are enabled") + if hostConfig.NetworkMode.IsHost() { + return warnings, fmt.Errorf("Cannot share the host's network namespace when user namespaces are enabled") } if hostConfig.PidMode.IsHost() { return warnings, fmt.Errorf("Cannot share the host PID namespace when user namespaces are enabled") } - if hostConfig.IpcMode.IsContainer() { - return warnings, fmt.Errorf("Cannot share a container's IPC namespace when user namespaces are enabled") - } if hostConfig.ReadonlyRootfs { return warnings, fmt.Errorf("Cannot use the --read-only option when user namespaces are enabled") } diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go index 0b61f5326b..f00e0416a6 100644 --- a/daemon/oci_linux.go +++ b/daemon/oci_linux.go @@ -230,6 +230,18 @@ func delNamespace(s *specs.Spec, nsType specs.NamespaceType) { } func setNamespaces(daemon *Daemon, s *specs.Spec, c *container.Container) error { + userNS := false + // user + if c.HostConfig.UsernsMode.IsPrivate() { + uidMap, gidMap := daemon.GetUIDGIDMaps() + if uidMap != nil { + userNS = true + ns := specs.Namespace{Type: "user"} + setNamespace(s, ns) + s.Linux.UIDMappings = specMapping(uidMap) + s.Linux.GIDMappings = specMapping(gidMap) + } + } // network if !c.Config.NetworkDisabled { ns := specs.Namespace{Type: "network"} @@ -240,6 +252,12 @@ func setNamespaces(daemon *Daemon, s *specs.Spec, c *container.Container) error return err } ns.Path = fmt.Sprintf("/proc/%d/ns/net", nc.State.GetPID()) + if userNS { + // to share a net namespace, they must also share a user namespace + nsUser := specs.Namespace{Type: "user"} + nsUser.Path = fmt.Sprintf("/proc/%d/ns/user", nc.State.GetPID()) + setNamespace(s, nsUser) + } } else if c.HostConfig.NetworkMode.IsHost() { ns.Path = c.NetworkSettings.SandboxKey } @@ -254,6 +272,12 @@ func setNamespaces(daemon *Daemon, s *specs.Spec, c *container.Container) error } ns.Path = fmt.Sprintf("/proc/%d/ns/ipc", ic.State.GetPID()) setNamespace(s, ns) + if userNS { + // to share an IPC namespace, they must also share a user namespace + nsUser := specs.Namespace{Type: "user"} + nsUser.Path = fmt.Sprintf("/proc/%d/ns/user", ic.State.GetPID()) + setNamespace(s, nsUser) + } } else if c.HostConfig.IpcMode.IsHost() { delNamespace(s, specs.NamespaceType("ipc")) } else { @@ -269,16 +293,6 @@ func setNamespaces(daemon *Daemon, s *specs.Spec, c *container.Container) error delNamespace(s, specs.NamespaceType("uts")) s.Hostname = "" } - // user - if c.HostConfig.UsernsMode.IsPrivate() { - uidMap, gidMap := daemon.GetUIDGIDMaps() - if uidMap != nil { - ns := specs.Namespace{Type: "user"} - setNamespace(s, ns) - s.Linux.UIDMappings = specMapping(uidMap) - s.Linux.GIDMappings = specMapping(gidMap) - } - } return nil } diff --git a/docs/reference/commandline/daemon.md b/docs/reference/commandline/daemon.md index 20ea3cb20e..61ba1c763d 100644 --- a/docs/reference/commandline/daemon.md +++ b/docs/reference/commandline/daemon.md @@ -792,11 +792,9 @@ The following standard Docker features are currently incompatible when running a Docker daemon with user namespaces enabled: - sharing PID or NET namespaces with the host (`--pid=host` or `--net=host`) - - sharing a network namespace with an existing container (`--net=container:*other*`) - - sharing an IPC namespace with an existing container (`--ipc=container:*other*`) - A `--readonly` container filesystem (this is a Linux kernel restriction against remounting with modified flags of a currently mounted filesystem when inside a user namespace) - external (volume or graph) drivers which are unaware/incapable of using daemon user mappings - - Using `--privileged` mode flag on `docker run` + - Using `--privileged` mode flag on `docker run` (unless also specifying `--userns=host`) In general, user namespaces are an advanced feature and will require coordination with other capabilities. For example, if volumes are mounted from