From 3d783d5dbf9b3074bda56496304450a818cc9fc9 Mon Sep 17 00:00:00 2001 From: Justin Cormack Date: Wed, 14 Mar 2018 09:55:54 +0000 Subject: [PATCH] If container will run as non root user, drop permitted, effective caps early As soon as the initial executable in the container is executed as a non root user, permitted and effective capabilities are dropped. Drop them earlier than this, so that they are dropped before executing the file. The main effect of this is that if `CAP_DAC_OVERRIDE` is set (the default) the user will not be able to execute files they do not have permission to execute, which previously they could. The old behaviour was somewhat surprising and the new one is definitely correct, but it is not in any meaningful way exploitable, and I do not think it is necessary to backport this fix. It is unlikely to have any negative effects as almost all executables have world execute permission anyway. Use the bounding set not the effective set as the canonical set of capabilities, as effective will now vary. Signed-off-by: Justin Cormack Upstream-commit: 15ff09395c001bcb0f284461abbc404a1d8bab4d Component: engine --- components/engine/daemon/oci_linux.go | 8 +++++++- components/engine/profiles/seccomp/seccomp.go | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/components/engine/daemon/oci_linux.go b/components/engine/daemon/oci_linux.go index 256e1c3e55..a83f155fda 100644 --- a/components/engine/daemon/oci_linux.go +++ b/components/engine/daemon/oci_linux.go @@ -255,7 +255,7 @@ func setCapabilities(s *specs.Spec, c *container.Container) error { if c.HostConfig.Privileged { caplist = caps.GetAllCapabilities() } else { - caplist, err = caps.TweakCapabilities(s.Process.Capabilities.Effective, c.HostConfig.CapAdd, c.HostConfig.CapDrop) + caplist, err = caps.TweakCapabilities(s.Process.Capabilities.Bounding, c.HostConfig.CapAdd, c.HostConfig.CapDrop) if err != nil { return err } @@ -264,6 +264,12 @@ func setCapabilities(s *specs.Spec, c *container.Container) error { 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/profiles/seccomp/seccomp.go b/components/engine/profiles/seccomp/seccomp.go index 36ec76ae05..4438670a58 100644 --- a/components/engine/profiles/seccomp/seccomp.go +++ b/components/engine/profiles/seccomp/seccomp.go @@ -105,7 +105,7 @@ Loop: } if len(call.Excludes.Caps) > 0 { for _, c := range call.Excludes.Caps { - if inSlice(rs.Process.Capabilities.Effective, c) { + if inSlice(rs.Process.Capabilities.Bounding, c) { continue Loop } } @@ -117,7 +117,7 @@ Loop: } if len(call.Includes.Caps) > 0 { for _, c := range call.Includes.Caps { - if !inSlice(rs.Process.Capabilities.Effective, c) { + if !inSlice(rs.Process.Capabilities.Bounding, c) { continue Loop } }