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 <justin.cormack@docker.com>
This commit is contained in:
Justin Cormack 2018-03-14 09:55:54 +00:00
parent 60e2dc2686
commit 15ff09395c
No known key found for this signature in database
GPG Key ID: 609102888A2EE3F9
2 changed files with 9 additions and 3 deletions

View File

@ -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
}

View File

@ -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
}
}