From ccb4f79c21910a7bc9ba5d8c838704a954819086 Mon Sep 17 00:00:00 2001 From: John Starks Date: Fri, 15 Jun 2018 15:36:10 -0700 Subject: [PATCH 1/2] lcow: Allow the client to add or remove capabilities Signed-off-by: John Starks Upstream-commit: 349aeeab7c5e878ddc6c0c95a0a937476816c43e Component: engine --- .../daemon/caps/{utils_unix.go => utils.go} | 2 -- components/engine/daemon/oci.go | 31 +++++++++++++++++++ components/engine/daemon/oci_linux.go | 25 --------------- components/engine/daemon/oci_windows.go | 10 ++++-- 4 files changed, 39 insertions(+), 29 deletions(-) rename components/engine/daemon/caps/{utils_unix.go => utils.go} (99%) create mode 100644 components/engine/daemon/oci.go diff --git a/components/engine/daemon/caps/utils_unix.go b/components/engine/daemon/caps/utils.go similarity index 99% rename from components/engine/daemon/caps/utils_unix.go rename to components/engine/daemon/caps/utils.go index 4c18b28be5..c5ded542ef 100644 --- a/components/engine/daemon/caps/utils_unix.go +++ b/components/engine/daemon/caps/utils.go @@ -1,5 +1,3 @@ -// +build !windows - package caps // import "github.com/docker/docker/daemon/caps" import ( diff --git a/components/engine/daemon/oci.go b/components/engine/daemon/oci.go new file mode 100644 index 0000000000..f3a556c617 --- /dev/null +++ b/components/engine/daemon/oci.go @@ -0,0 +1,31 @@ +package daemon // import "github.com/docker/docker/daemon" + +import ( + "github.com/docker/docker/container" + "github.com/docker/docker/daemon/caps" + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +func setCapabilities(s *specs.Spec, c *container.Container) error { + var caplist []string + var err error + if c.HostConfig.Privileged { + caplist = caps.GetAllCapabilities() + } else { + caplist, err = caps.TweakCapabilities(s.Process.Capabilities.Bounding, c.HostConfig.CapAdd, c.HostConfig.CapDrop) + if err != nil { + return err + } + } + s.Process.Capabilities.Effective = caplist + s.Process.Capabilities.Bounding = caplist + s.Process.Capabilities.Permitted = caplist + s.Process.Capabilities.Inheritable = caplist + // setUser has already been executed here + // if non root drop capabilities in the way execve does + if s.Process.User.UID != 0 { + s.Process.Capabilities.Effective = []string{} + s.Process.Capabilities.Permitted = []string{} + } + return nil +} diff --git a/components/engine/daemon/oci_linux.go b/components/engine/daemon/oci_linux.go index 9b39a64ee7..37e289934b 100644 --- a/components/engine/daemon/oci_linux.go +++ b/components/engine/daemon/oci_linux.go @@ -13,7 +13,6 @@ import ( containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" - "github.com/docker/docker/daemon/caps" daemonconfig "github.com/docker/docker/daemon/config" "github.com/docker/docker/oci" "github.com/docker/docker/pkg/idtools" @@ -249,30 +248,6 @@ func setNamespace(s *specs.Spec, ns specs.LinuxNamespace) { s.Linux.Namespaces = append(s.Linux.Namespaces, ns) } -func setCapabilities(s *specs.Spec, c *container.Container) error { - var caplist []string - var err error - if c.HostConfig.Privileged { - caplist = caps.GetAllCapabilities() - } else { - caplist, err = caps.TweakCapabilities(s.Process.Capabilities.Bounding, c.HostConfig.CapAdd, c.HostConfig.CapDrop) - if err != nil { - return err - } - } - s.Process.Capabilities.Effective = caplist - s.Process.Capabilities.Bounding = caplist - s.Process.Capabilities.Permitted = caplist - s.Process.Capabilities.Inheritable = caplist - // setUser has already been executed here - // if non root drop capabilities in the way execve does - if s.Process.User.UID != 0 { - s.Process.Capabilities.Effective = []string{} - s.Process.Capabilities.Permitted = []string{} - } - return nil -} - func setNamespaces(daemon *Daemon, s *specs.Spec, c *container.Container) error { userNS := false // user diff --git a/components/engine/daemon/oci_windows.go b/components/engine/daemon/oci_windows.go index f00ab3363d..d3631b9d92 100644 --- a/components/engine/daemon/oci_windows.go +++ b/components/engine/daemon/oci_windows.go @@ -211,7 +211,9 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { if !system.LCOWSupported() { return nil, fmt.Errorf("Linux containers on Windows are not supported") } - daemon.createSpecLinuxFields(c, &s) + if err := daemon.createSpecLinuxFields(c, &s); err != nil { + return nil, err + } default: return nil, fmt.Errorf("Unsupported platform %q", img.OS) } @@ -336,12 +338,16 @@ func (daemon *Daemon) createSpecWindowsFields(c *container.Container, s *specs.S // Sets the Linux-specific fields of the OCI spec // TODO: @jhowardmsft LCOW Support. We need to do a lot more pulling in what can // be pulled in from oci_linux.go. -func (daemon *Daemon) createSpecLinuxFields(c *container.Container, s *specs.Spec) { +func (daemon *Daemon) createSpecLinuxFields(c *container.Container, s *specs.Spec) error { if len(s.Process.Cwd) == 0 { s.Process.Cwd = `/` } s.Root.Path = "rootfs" s.Root.Readonly = c.HostConfig.ReadonlyRootfs + if err := setCapabilities(s, c); err != nil { + return fmt.Errorf("linux spec capabilities: %v", err) + } + return nil } func escapeArgs(args []string) []string { From 92efea70f88e1100703d212f45024494692f8e49 Mon Sep 17 00:00:00 2001 From: John Starks Date: Fri, 15 Jun 2018 16:14:17 -0700 Subject: [PATCH 2/2] lcow: Allow the client to add device cgroup rules Signed-off-by: John Starks Upstream-commit: e9268d96420227550998212789f7058afc297de9 Component: engine --- components/engine/daemon/oci.go | 47 +++++++++++++++++++++++++ components/engine/daemon/oci_linux.go | 43 +++------------------- components/engine/daemon/oci_windows.go | 5 +++ 3 files changed, 56 insertions(+), 39 deletions(-) diff --git a/components/engine/daemon/oci.go b/components/engine/daemon/oci.go index f3a556c617..52050e24fa 100644 --- a/components/engine/daemon/oci.go +++ b/components/engine/daemon/oci.go @@ -1,11 +1,20 @@ package daemon // import "github.com/docker/docker/daemon" import ( + "fmt" + "regexp" + "strconv" + "github.com/docker/docker/container" "github.com/docker/docker/daemon/caps" specs "github.com/opencontainers/runtime-spec/specs-go" ) +// nolint: gosimple +var ( + deviceCgroupRuleRegex = regexp.MustCompile("^([acb]) ([0-9]+|\\*):([0-9]+|\\*) ([rwm]{1,3})$") +) + func setCapabilities(s *specs.Spec, c *container.Container) error { var caplist []string var err error @@ -29,3 +38,41 @@ func setCapabilities(s *specs.Spec, c *container.Container) error { } return nil } + +func appendDevicePermissionsFromCgroupRules(devPermissions []specs.LinuxDeviceCgroup, rules []string) ([]specs.LinuxDeviceCgroup, error) { + for _, deviceCgroupRule := range rules { + ss := deviceCgroupRuleRegex.FindAllStringSubmatch(deviceCgroupRule, -1) + if len(ss[0]) != 5 { + return nil, fmt.Errorf("invalid device cgroup rule format: '%s'", deviceCgroupRule) + } + matches := ss[0] + + dPermissions := specs.LinuxDeviceCgroup{ + Allow: true, + Type: matches[1], + Access: matches[4], + } + if matches[2] == "*" { + major := int64(-1) + dPermissions.Major = &major + } else { + major, err := strconv.ParseInt(matches[2], 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid major value in device cgroup rule format: '%s'", deviceCgroupRule) + } + dPermissions.Major = &major + } + if matches[3] == "*" { + minor := int64(-1) + dPermissions.Minor = &minor + } else { + minor, err := strconv.ParseInt(matches[3], 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid minor value in device cgroup rule format: '%s'", deviceCgroupRule) + } + dPermissions.Minor = &minor + } + devPermissions = append(devPermissions, dPermissions) + } + return devPermissions, nil +} diff --git a/components/engine/daemon/oci_linux.go b/components/engine/daemon/oci_linux.go index 37e289934b..6fb7a26dcb 100644 --- a/components/engine/daemon/oci_linux.go +++ b/components/engine/daemon/oci_linux.go @@ -6,7 +6,6 @@ import ( "os" "os/exec" "path/filepath" - "regexp" "sort" "strconv" "strings" @@ -28,11 +27,6 @@ import ( "golang.org/x/sys/unix" ) -// nolint: gosimple -var ( - deviceCgroupRuleRegex = regexp.MustCompile("^([acb]) ([0-9]+|\\*):([0-9]+|\\*) ([rwm]{1,3})$") -) - func setResources(s *specs.Spec, r containertypes.Resources) error { weightDevices, err := getBlkioWeightDevices(r) if err != nil { @@ -114,39 +108,10 @@ func setDevices(s *specs.Spec, c *container.Container) error { devPermissions = append(devPermissions, dPermissions...) } - for _, deviceCgroupRule := range c.HostConfig.DeviceCgroupRules { - ss := deviceCgroupRuleRegex.FindAllStringSubmatch(deviceCgroupRule, -1) - if len(ss[0]) != 5 { - return fmt.Errorf("invalid device cgroup rule format: '%s'", deviceCgroupRule) - } - matches := ss[0] - - dPermissions := specs.LinuxDeviceCgroup{ - Allow: true, - Type: matches[1], - Access: matches[4], - } - if matches[2] == "*" { - major := int64(-1) - dPermissions.Major = &major - } else { - major, err := strconv.ParseInt(matches[2], 10, 64) - if err != nil { - return fmt.Errorf("invalid major value in device cgroup rule format: '%s'", deviceCgroupRule) - } - dPermissions.Major = &major - } - if matches[3] == "*" { - minor := int64(-1) - dPermissions.Minor = &minor - } else { - minor, err := strconv.ParseInt(matches[3], 10, 64) - if err != nil { - return fmt.Errorf("invalid minor value in device cgroup rule format: '%s'", deviceCgroupRule) - } - dPermissions.Minor = &minor - } - devPermissions = append(devPermissions, dPermissions) + var err error + devPermissions, err = appendDevicePermissionsFromCgroupRules(devPermissions, c.HostConfig.DeviceCgroupRules) + if err != nil { + return err } } diff --git a/components/engine/daemon/oci_windows.go b/components/engine/daemon/oci_windows.go index d3631b9d92..6279d7dd20 100644 --- a/components/engine/daemon/oci_windows.go +++ b/components/engine/daemon/oci_windows.go @@ -347,6 +347,11 @@ func (daemon *Daemon) createSpecLinuxFields(c *container.Container, s *specs.Spe if err := setCapabilities(s, c); err != nil { return fmt.Errorf("linux spec capabilities: %v", err) } + devPermissions, err := appendDevicePermissionsFromCgroupRules(nil, c.HostConfig.DeviceCgroupRules) + if err != nil { + return fmt.Errorf("linux runtime spec devices: %v", err) + } + s.Linux.Resources.Devices = devPermissions return nil }