From 6934594ae04192c12a747f088c49599ce886058e Mon Sep 17 00:00:00 2001 From: Qiang Huang Date: Sat, 23 Jan 2016 10:15:09 +0800 Subject: [PATCH] Verify cgroup-parent name for systemd cgroup Fixes: #17126 Signed-off-by: Qiang Huang --- daemon/container_operations_unix.go | 13 ++--------- daemon/daemon.go | 4 ++-- daemon/daemon_unix.go | 34 +++++++++++++++++++++++++++-- daemon/daemon_windows.go | 4 ++-- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go index 5e159898f5..04496133a7 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -21,7 +21,6 @@ import ( "github.com/docker/docker/pkg/fileutils" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/mount" - "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/runconfig" containertypes "github.com/docker/engine-api/types/container" @@ -249,16 +248,8 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro defaultCgroupParent := "/docker" if daemon.configStore.CgroupParent != "" { defaultCgroupParent = daemon.configStore.CgroupParent - } else { - for _, option := range daemon.configStore.ExecOptions { - key, val, err := parsers.ParseKeyValueOpt(option) - if err != nil || !strings.EqualFold(key, "native.cgroupdriver") { - continue - } - if val == "systemd" { - defaultCgroupParent = "system.slice" - } - } + } else if daemon.usingSystemd() { + defaultCgroupParent = "system.slice" } c.Command = &execdriver.Command{ CommonCommand: execdriver.CommonCommand{ diff --git a/daemon/daemon.go b/daemon/daemon.go index 8af07f38c6..79c58ec3ac 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -595,8 +595,8 @@ func (daemon *Daemon) registerLink(parent, child *container.Container, alias str func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) { setDefaultMtu(config) - // Ensure we have compatible configuration options - if err := checkConfigOptions(config); err != nil { + // Ensure we have compatible and valid configuration options + if err := verifyDaemonSettings(config); err != nil { return nil, err } diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 45fb48635c..cfa9ef1ddb 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -18,6 +18,7 @@ import ( "github.com/docker/docker/image" "github.com/docker/docker/layer" "github.com/docker/docker/pkg/idtools" + "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/sysinfo" "github.com/docker/docker/reference" @@ -361,6 +362,24 @@ func verifyContainerResources(resources *containertypes.Resources) ([]string, er return warnings, nil } +func usingSystemd(config *Config) bool { + for _, option := range config.ExecOptions { + key, val, err := parsers.ParseKeyValueOpt(option) + if err != nil || !strings.EqualFold(key, "native.cgroupdriver") { + continue + } + if val == "systemd" { + return true + } + } + + return false +} + +func (daemon *Daemon) usingSystemd() bool { + return usingSystemd(daemon.configStore) +} + // verifyPlatformContainerSettings performs platform-specific validation of the // hostconfig and config structures. func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config) ([]string, error) { @@ -407,11 +426,17 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. return warnings, fmt.Errorf("Cannot use the --read-only option when user namespaces are enabled.") } } + if hostConfig.CgroupParent != "" && daemon.usingSystemd() { + // CgroupParent for systemd cgroup should be named as "xxx.slice" + if len(hostConfig.CgroupParent) <= 6 || !strings.HasSuffix(hostConfig.CgroupParent, ".slice") { + return warnings, fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"") + } + } return warnings, nil } -// checkConfigOptions checks for mutually incompatible config options -func checkConfigOptions(config *Config) error { +// verifyDaemonSettings performs validation of daemon config struct +func verifyDaemonSettings(config *Config) error { // Check for mutually incompatible config options if config.bridgeConfig.Iface != "" && config.bridgeConfig.IP != "" { return fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.") @@ -422,6 +447,11 @@ func checkConfigOptions(config *Config) error { if !config.bridgeConfig.EnableIPTables && config.bridgeConfig.EnableIPMasq { config.bridgeConfig.EnableIPMasq = false } + if config.CgroupParent != "" && usingSystemd(config) { + if len(config.CgroupParent) <= 6 || !strings.HasSuffix(config.CgroupParent, ".slice") { + return fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"") + } + } return nil } diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go index 45b0975c08..e5db1a8b74 100644 --- a/daemon/daemon_windows.go +++ b/daemon/daemon_windows.go @@ -88,8 +88,8 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. return nil, nil } -// checkConfigOptions checks for mutually incompatible config options -func checkConfigOptions(config *Config) error { +// verifyDaemonSettings performs validation of daemon config struct +func verifyDaemonSettings(config *Config) error { return nil }