diff --git a/cmd/dockerd/config_unix.go b/cmd/dockerd/config_unix.go index 1817c1da27..8cc11ae0a9 100644 --- a/cmd/dockerd/config_unix.go +++ b/cmd/dockerd/config_unix.go @@ -9,6 +9,7 @@ import ( "github.com/docker/docker/opts" "github.com/docker/docker/rootless" units "github.com/docker/go-units" + "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/pkg/errors" "github.com/spf13/pflag" ) @@ -64,6 +65,10 @@ func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) error { // rootless needs to be explicitly specified for running "rootful" dockerd in rootless dockerd (#38702) // Note that defaultUserlandProxyPath and honorXDG are configured according to the value of rootless.RunningWithRootlessKit, not the value of --rootless. flags.BoolVar(&conf.Rootless, "rootless", rootless.RunningWithRootlessKit(), "Enable rootless mode; typically used with RootlessKit (experimental)") - flags.StringVar(&conf.CgroupNamespaceMode, "default-cgroupns-mode", config.DefaultCgroupNamespaceMode, `Default mode for containers cgroup namespace ("host" | "private")`) + defaultCgroupNamespaceMode := "host" + if cgroups.IsCgroup2UnifiedMode() { + defaultCgroupNamespaceMode = "private" + } + flags.StringVar(&conf.CgroupNamespaceMode, "default-cgroupns-mode", defaultCgroupNamespaceMode, `Default mode for containers cgroup namespace ("host" | "private")`) return nil } diff --git a/daemon/config/config_unix.go b/daemon/config/config_unix.go index 92076d4d7f..343b85fef7 100644 --- a/daemon/config/config_unix.go +++ b/daemon/config/config_unix.go @@ -11,8 +11,6 @@ import ( ) const ( - // DefaultCgroupNamespaceMode is the default for a container's CgroupnsMode, if not set otherwise - DefaultCgroupNamespaceMode = "host" // TODO: change to private // DefaultIpcMode is default for container's IpcMode, if not set otherwise DefaultIpcMode = "private" ) diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 92d6a5440f..fc3a25cf25 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -364,10 +364,15 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf // Set default cgroup namespace mode, if unset for container if hostConfig.CgroupnsMode.IsEmpty() { - if hostConfig.Privileged { + // for cgroup v2: unshare cgroupns even for privileged containers + // https://github.com/containers/libpod/pull/4374#issuecomment-549776387 + if hostConfig.Privileged && !cgroups.IsCgroup2UnifiedMode() { hostConfig.CgroupnsMode = containertypes.CgroupnsMode("host") } else { - m := config.DefaultCgroupNamespaceMode + m := "host" + if cgroups.IsCgroup2UnifiedMode() { + m = "private" + } if daemon.configStore != nil { m = daemon.configStore.CgroupNamespaceMode } @@ -708,8 +713,8 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. warnings = append(warnings, "Your kernel does not support cgroup namespaces. Cgroup namespace setting discarded.") } - if hostConfig.Privileged { - return warnings, fmt.Errorf("privileged mode is incompatible with private cgroup namespaces. You must run the container in the host cgroup namespace when running privileged mode") + if hostConfig.Privileged && !cgroups.IsCgroup2UnifiedMode() { + return warnings, fmt.Errorf("privileged mode is incompatible with private cgroup namespaces on cgroup v1 host. You must run the container in the host cgroup namespace when running privileged mode") } } diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go index 65d2e48ef7..638696e121 100644 --- a/daemon/oci_linux.go +++ b/daemon/oci_linux.go @@ -316,7 +316,9 @@ func WithNamespaces(daemon *Daemon, c *container.Container) coci.SpecOpts { return fmt.Errorf("invalid cgroup namespace mode: %v", cgroupNsMode) } - if cgroupNsMode.IsPrivate() && !c.HostConfig.Privileged { + // for cgroup v2: unshare cgroupns even for privileged containers + // https://github.com/containers/libpod/pull/4374#issuecomment-549776387 + if cgroupNsMode.IsPrivate() && (cgroups.IsCgroup2UnifiedMode() || !c.HostConfig.Privileged) { nsCgroup := specs.LinuxNamespace{Type: "cgroup"} setNamespace(s, nsCgroup) } diff --git a/integration/container/run_cgroupns_linux_test.go b/integration/container/run_cgroupns_linux_test.go index 64c18fa281..f06d01e3da 100644 --- a/integration/container/run_cgroupns_linux_test.go +++ b/integration/container/run_cgroupns_linux_test.go @@ -115,7 +115,7 @@ func TestCgroupNamespacesRunPrivilegedAndPrivate(t *testing.T) { skip.If(t, !requirement.CgroupNamespacesEnabled()) // Running with both privileged and cgroupns=private is not allowed - errStr := "privileged mode is incompatible with private cgroup namespaces. You must run the container in the host cgroup namespace when running privileged mode" + errStr := "privileged mode is incompatible with private cgroup namespaces on cgroup v1 host. You must run the container in the host cgroup namespace when running privileged mode" testCreateFailureWithCgroupNs(t, "private", errStr, container.WithPrivileged(true), container.WithCgroupnsMode("private")) }